繁体   English   中英

CustomDeserializer 没有默认(无参数)构造函数

[英]CustomDeserializer has no default (no arg) constructor

我正在使用 RestTemplate 使用 REST Api。 我从 API 得到的响应有很多嵌套对象。 这里有一个小片段作为例子:

"formularios": [
  {
    "form_data_id": "123006",
    "form_data": {
      "form_data_id": "123006",
      "form_id": "111",
      "efs": {
        "1": {},
        "2": "{\"t\":\"c\",\"st\":\"m\",\"v\":[{\"id\":\"3675\",\"l\":\"a) Just an example\",\"v\":\"1\"},{\"id\":\"3676\",\"l\":\"b) Another example.\",\"v\":\"2\"}]}"
      }
    }

我遇到的问题是,大多数时候“1”实际上有内容,就像“2”一样,jackson 只是将它解析为对象“efs”上的字符串。 但有时,就像在代码片段中一样,API 将其发送为空,而 jackson 将其作为对象,这给了我一个错误,说明了 START_OBJECT(不记得确切的错误,但对于这个问题并不重要) )。

所以我决定制作一个自定义反序列化器,这样当 jackson 读取“1”时,它会忽略空对象并将其解析为空字符串。

这是我的自定义解串器:

public class CustomDeserializer extends StdDeserializer<Efs> {

 public CustomDeserializer(Class<Efs> t) {
     super(t);
 }

 @Override
 public Efs deserialize(JsonParser jp, DeserializationContext dc)
         throws IOException, JsonProcessingException {

     String string1 = null;
     String string2 = null;
     JsonToken currentToken = null;

     while ((currentToken = jp.nextValue()) != null) {
         if (currentToken.equals(JsonToken.VALUE_STRING)) {
             if (jp.getCurrentName().equals("1")) {
                 string1 = jp.getValueAsString();
             } else {
                 string2 = jp.getValueAsString();
             }

         } else {
             if (jp.getCurrentName().equals("2")) {
                 string2 = jp.getValueAsString();
             }

         }
     }
     return new Efs(string1, string2);

  }
 }

这是我从 API 接收响应时使用它的方式:

    ObjectMapper mapper = new ObjectMapper();  
    SimpleModule mod = new SimpleModule("EfsModule");
    mod.addDeserializer(Efs.class, new CustomDeserializer(Efs.class));
    mapper.registerModule(mod);


    List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
    MappingJackson2HttpMessageConverter jsonMessageConverter = new MappingJackson2HttpMessageConverter();
    jsonMessageConverter.setObjectMapper(mapper);
    messageConverters.add(jsonMessageConverter);


    RestTemplate restTemplate = new RestTemplate();
    restTemplate.setMessageConverters(messageConverters);

我收到错误:

 CustomDeserializer has no default (no arg) constructor

但我不知道我做错了什么,也不知道如何解决。 感谢您对这么长的问题的帮助和道歉,我想提供尽可能多的背景信息。

还有一个用户可能会陷入的陷阱(比如我自己)。 如果您将反序列化器声明为内部类(不是静态嵌套类),例如:

@JsonDeserialize(using = DomainObjectDeserializer.class)
public class DomainObject {
    private String key;

    public class DomainObjectDeserializer extends StdDeserializer<DomainObject> {
        public DomainObjectDeserializer() {
            super(DomainObject.class);
        }

        @Override
        public DomainObject deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            // code
        }
    }
}

Jackson 使用Class#getDeclaredConstructor()没有参数(方法接受vararg ),这意味着:给我一个默认(无参数)构造函数。 当 Jackson 尝试创建DomainObjectDeserializer时,上面的代码将抛出异常,因为javac确实生成了接受封闭类引用的构造函数。 从技术上讲, DomainObjectDeserializer没有默认构造函数。

出于好奇,您可以执行DomainObjectDeserializer.class.getDeclaredConstructors()并确保该方法确实返回包含带有封闭类引用的构造函数定义的单元素数组。

DomainObjectDeserializer应声明为static类。

这是一个很好的答案,可以详细阅读。

要求您有一个不带参数的默认构造函数。 您可以做的是创建一个(如果您真的不需要,则替换另一个):

public class CustomDeserializer extends StdDeserializer<Efs> {

   public CustomDeserializer() {
       super(Efs.class);
   }
   ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM