无法使用 Jackson 从对象值(无委托或基于 属性 的创建者)反序列化
Cannot deserialize from Object value (no delegate- or property-based Creator) using Jackson
我正在尝试使用 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]
我创建了两个 classes。第一个class:
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;
}
和第二个class
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;
}
主要class:
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>
消息很清楚:(no Creators, like default construct, exist)
您需要向 class 或 NoArgsConstructor
注释添加无参数构造函数:
@Data
public class DeserializeSubscription {
public DeserializeSubscription (){}
或
@NoArgsConstructor
@Data
public class DeserializeSubscription {
你要考虑几个情况:
message
JSON
中的字段是原始的 String
。在 POJO
级别,它是一个 MessageSubscription
对象。
message
JSON
中的值包含未加引号的 属性 名称,这是非法的,但 Jackson
也会处理它们。
- 如果构造函数不适合
JSON
我们需要使用注释来配置它。
要处理不带引号的名称,我们需要启用 ALLOW_UNQUOTED_FIELD_NAMES 功能。为了处理 JSON
有效负载和 POJO
之间的不匹配,我们需要为 MessageSubscription
class.
实现自定义反序列化器
自定义解串器可能如下所示:
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))
这可能是由于使用了不受支持的数据类型,例如无符号整数。
我在反序列化具有 ULong 字段的 JSON 对象时收到此错误。并通过将字段类型更改为普通有符号(长)整数来解决它。
我正在尝试使用 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]
我创建了两个 classes。第一个class:
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;
}
和第二个class
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;
}
主要class:
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>
消息很清楚:(no Creators, like default construct, exist)
您需要向 class 或 NoArgsConstructor
注释添加无参数构造函数:
@Data
public class DeserializeSubscription {
public DeserializeSubscription (){}
或
@NoArgsConstructor
@Data
public class DeserializeSubscription {
你要考虑几个情况:
message
JSON
中的字段是原始的String
。在POJO
级别,它是一个MessageSubscription
对象。message
JSON
中的值包含未加引号的 属性 名称,这是非法的,但Jackson
也会处理它们。- 如果构造函数不适合
JSON
我们需要使用注释来配置它。
要处理不带引号的名称,我们需要启用 ALLOW_UNQUOTED_FIELD_NAMES 功能。为了处理 JSON
有效负载和 POJO
之间的不匹配,我们需要为 MessageSubscription
class.
自定义解串器可能如下所示:
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))
这可能是由于使用了不受支持的数据类型,例如无符号整数。
我在反序列化具有 ULong 字段的 JSON 对象时收到此错误。并通过将字段类型更改为普通有符号(长)整数来解决它。