Java 无法使用Jackson从对象值(无委托或基于属性的创建者)反序列化

Java 无法使用Jackson从对象值(无委托或基于属性的创建者)反序列化,java,json,jackson,deserialization,json-deserialization,Java,Json,Jackson,Deserialization,Json Deserialization,我正在尝试使用Jackson反序列化下面的JSON负载: {"code":null,"reason":"subscription yet available","message":"{ Message:\"subscription yet available\", SubscriptionUID:\"46b62920-c519-4555-8973-3b28a7a29463\" }"} 但是我得到了这个JsonMappingException: Cannot construct instance

我正在尝试使用
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();
                 }
我找到了这个解决方案,但我没有成功

我在应用程序中使用的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>

com.fasterxml.jackson.core
杰克逊数据绑定
2.10.2

信息非常清楚:
(不存在像默认构造那样的创建者)

您需要向类或
noargsconstuctor
注释添加无参数构造函数:

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


你必须考虑很少的情况:

  • JSON
    中的
    message
    字段是原始的
    String
    。在
    POJO
    级别,它是一个
    MessageSubscription
    对象
  • JSON
    中的
    message
    值包含不带引号的属性名,这是非法的,但
    Jackson
    也会处理它们
  • 如果构造函数不适合
    JSON
    ,我们需要使用注释对其进行配置
要处理不带引号的名称,我们需要启用该功能。为了处理
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);
    }
}
示例如何使用它:

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
payload示例打印:

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

对不起,我以前尝试过第一种解决方案,但第二种解决方案的结果相同solution@Scripta14*与第二个解决方案*的结果相同,结果是什么?相同的例外:
无法构造'com.ids.utilities.DeserializeSubscription'的实例(不存在与默认构造类似的创建者):无法从[Source:“String”{“code”:null,“reason:“subscription尚未可用”,“message:“{message:\“subscription尚未可用\”,SubscriptionUID:\“46b62920-c519-4555-8973-3b28a7a29463\”};行:1,列:2];反序列化对象值(无委托或基于属性的创建者);非常感谢您的解决方案。。不幸的是,我复制了您的代码,但出现了以下错误:
线程“main”中的异常com.fasterxml.jackson.databind.JsonMappingException:Source:(String){Message::line:1,column:3](通过引用链:test.exatest.DeserializeSubscription[“Message”])处的对象条目内/之间的输入意外结束
。我已经使用了我的jsonstring@Scripta14,可能您已经破坏了
JSON
负载。另外,您是否启用了
JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES
功能?我已经对您的负载进行了测试,效果很好。您使用的是
Jackson
的哪个版本?上面我编写了我在a中使用的Jackson-maven版本应用程序。我复制了你的代码。唯一不同的是,我使用了我在这篇文章上面写的json字符串。@Scripta14,你是否正确转义了
json
payload?payload:
“{\“code\”:null,\“reason\”:“subscription尚未可用”,“message\”:“{message:\\\”subscription尚未可用\\\”,SubscriptionUID:\\\“46b62920-c519-4555-8973-3b28a7a29463\\\\\\\\\\\\\\\\\\\\”}”
非常感谢……它在json有效负载中运行良好,缺少一些转义
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);
    }
}
DeserializeSubscription(code=null, reason=subscription yet available, message=MessageSubscription(message=subscription yet available, subscriptionUID=46b62920-c519-4555-8973-3b28a7a29463))