【问题标题】:Cannot deserialize from Object value (no delegate- or property-based Creator) using Jackson无法使用 Jackson 反序列化 Object 值(没有基于委托或基于属性的 Creator)
【发布时间】:2020-06-28 10:34:38
【问题描述】:

我正在尝试使用Jackson 反序列化JSON 有效负载:

{"code":null,"reason":"subscription yet available","message":"{ Message:\"subscription yet available\", SubscriptionUID:\"46b62920-c519-4555-8973-3b28a7a29463\" }"}

但我收到了这个JsonMappingException

Cannot construct instance of `com.ids.utilities.DeserializeSubscription` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (String)"{"code":null,"reason":"subscription yet available","message":"{ Message:\"subscription yet available\", SubscriptionUID:\"46b62920-c519-4555-8973-3b28a7a29463\" }"}"; line: 1, column: 2]

我创建了两个类。第一课:

import lombok.Data;

@Data
public class DeserializeSubscription {

    private String code;
    private String reason;
    private MessageSubscription message;


    public DeserializeSubscription(String code, String reason, MessageSubscription message) {
        super();
        this.code = code;
        this.reason = reason;
        this.message = message;
    }

还有二等

import lombok.Data;

@Data
public class MessageSubscription {

    private String message;
    private String subscriptionUID;


    public MessageSubscription(String message, String subscriptionUID) {
        super();
        this.message = message;
        this.subscriptionUID = subscriptionUID;
    }

在主类中:

                 try 
                 {

                    ObjectMapper mapper = new ObjectMapper();
                    mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
                    DeserializeSubscription desSub=null;

                    desSub=mapper.readValue(e.getResponseBody(), DeserializeSubscription.class);

                    System.out.println(desSub.getMessage().getSubscriptionUID());
                 }
                 catch (JsonParseException e1) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                 }
                 catch (JsonMappingException e1) {
                     System.out.println(e1.getMessage());
                        e.printStackTrace();
                 }
                 catch (IOException e1) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                 }

我找到了这个解决方案,但我没有用它 https://facingissuesonit.com/2019/07/17/com-fasterxml-jackson-databind-exc-invaliddefinitionexception-cannot-construct-instance-of-xyz-no-creators-like-default-construct-exist-cannot-deserialize-from-object-value-no-delega/

我在应用程序中使用的 jackson maven

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.10.2</version>
    </dependency>

【问题讨论】:

    标签: java json jackson deserialization json-deserialization


    【解决方案1】:

    消息很清楚:(no Creators, like default construct, exist)

    您需要在类或NoArgsConstructor 注解中添加无参数构造函数:

    @Data
    public class DeserializeSubscription {
      public DeserializeSubscription (){}
    

    @NoArgsConstructor
    @Data
    public class DeserializeSubscription {
    

    【讨论】:

    • 对不起,我之前尝试过第一个解决方案,并与第二个解决方案获得相同的结果
    • @Scripta14* 与第二个解决方案的结果相同*,结果是什么?
    • 同样的例外:Cannot construct instance of `com.ids.utilities.DeserializeSubscription` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator) at [Source: (String)"{"code":null,"reason":"subscription yet available","message":"{ Message:\"subscription yet available\", SubscriptionUID:\"46b62920-c519-4555-8973-3b28a7a29463\" }"}"; line: 1, column: 2]
    【解决方案2】:

    你必须考虑几种情况:

    • JSON 中的 message 字段是原始的 String。在POJO 级别上,它是一个MessageSubscription 对象。
    • JSON 中的 message 值包含不带引号的属性名称,这是非法的,但 Jackson 也会处理它们。
    • 如果构造函数不适合JSON,我们需要使用注释对其进行配置。

    要处理不带引号的名称,我们需要启用ALLOW_UNQUOTED_FIELD_NAMES 功能。为了处理JSON 有效负载和POJO 之间的不匹配,我们需要为MessageSubscription 类实现自定义反序列化器。

    自定义反序列化器可能如下所示:

    class MessageSubscriptionJsonDeserializer extends JsonDeserializer<MessageSubscription> {
        @Override
        public MessageSubscription deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            final String value = p.getValueAsString();
            final Map<String, String> map = deserializeAsMap(value, (ObjectMapper) p.getCodec(), ctxt);
    
            return new MessageSubscription(map.get("Message"), map.get("SubscriptionUID"));
        }
    
        private Map<String, String> deserializeAsMap(String value, ObjectMapper mapper, DeserializationContext ctxt) throws IOException {
            final MapType mapType = ctxt.getTypeFactory().constructMapType(Map.class, String.class, String.class);
            return mapper.readValue(value, mapType);
        }
    }
    

    现在,我们需要自定义DeserializeSubscription的构造函数:

    @Data
    class DeserializeSubscription {
    
        private String code;
        private String reason;
        private MessageSubscription message;
    
        @JsonCreator
        public DeserializeSubscription(
                @JsonProperty("code") String code,
                @JsonProperty("reason") String reason,
                @JsonProperty("message") @JsonDeserialize(using = MessageSubscriptionJsonDeserializer.class) MessageSubscription message) {
            super();
            this.code = code;
            this.reason = reason;
            this.message = message;
        }
    }
    

    使用示例:

    import com.fasterxml.jackson.annotation.JsonCreator;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.databind.DeserializationContext;
    import com.fasterxml.jackson.databind.DeserializationFeature;
    import com.fasterxml.jackson.databind.JsonDeserializer;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
    import com.fasterxml.jackson.databind.type.MapType;
    import lombok.Data;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.Map;
    
    public class JsonPathApp {
    
        public static void main(String[] args) throws Exception {
            File jsonFile = new File("./resource/test.json").getAbsoluteFile();
    
            ObjectMapper mapper = new ObjectMapper();
            mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
            mapper.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES);
    
            DeserializeSubscription value = mapper.readValue(jsonFile, DeserializeSubscription.class);
            System.out.println(value);
        }
    }
    

    对于上面提供的JSON有效载荷示例打印:

    DeserializeSubscription(code=null, reason=subscription yet available, message=MessageSubscription(message=subscription yet available, subscriptionUID=46b62920-c519-4555-8973-3b28a7a29463))
    

    【讨论】:

    • 非常感谢您的解决方案。不幸的是,我复制了您的代码,但出现此错误:Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Unexpected end-of-input within/between Object entries at [Source: (String)"{ Message:"; line: 1, column: 3] (through reference chain: test.exatest.DeserializeSubscription["message"])。我已经使用了我的 json 字符串
    • @Scripta14,您可能已经破坏了JSON 有效负载。另外,您是否启用了JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES 功能?我已经针对您的有效负载对其进行了测试,并且效果很好。你用的是哪个版本的Jackson
    • 在上面我写了我在我的应用程序中使用的 Jackson maven 版本。我已经复制了你的代码。唯一不同的是,我使用了我在这篇文章上面写的 json 字符串。
    • @Scripta14,你有没有正确地转义JSON有效载荷?有效载荷:"{\"code\":null,\"reason\":\"subscription yet available\",\"message\":\"{ Message:\\\"subscription yet available\\\", SubscriptionUID:\\\"46b62920-c519-4555-8973-3b28a7a29463\\\" }\"}"
    • 非常感谢...您的 json 负载运行良好,但缺少一些转义
    【解决方案3】:

    这可能是由于使用了不受支持的数据类型,例如无符号整数。

    我在反序列化具有 ULong 字段的 JSON 对象时收到此错误。并通过将字段类型更改为普通有符号(长)整数来解决它。

    【讨论】:

      猜你喜欢
      • 2019-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多