java如何在Jackson中正确反序列化映射<String,Object>
我有以下可以序列化为字节或json
的POJO
public final class Message {
private final Data data;
private final Request request;
private final Response response;
public Message() {
this.data = new Data();
this.request = new Request();
this.response = new Response();
}
public Data getData() {
return data;
}
public Request getRequest() {
return request;
}
public Response getResponse() {
return response;
}
public Object query(String pointer) {
return toJson().query(pointer);
}
public byte[] toBytes() {
try {
return new ObjectMapper(new MessagePackFactory()).writeValueAsBytes(this);
} catch (JsonProcessingException ex) {
throw new MessageException(ex);
}
}
public JSONObject toJson() {
try {
return new JSONObject(new ObjectMapper().writeValueAsString(this));
} catch (JsonProcessingException ex) {
throw new MessageException(ex);
}
}
@Override
public String toString() {
try {
return toString(0);
} catch (MessageException ex) {
throw new MessageException(ex);
}
}
public String toString(int indent) {
try {
return toJson().toString(indent);
} catch (MessageException ex) {
throw new MessageException(ex);
}
}
}
参考类:
public class Data {
private final Map<String, Map<String, Object>> dataMap;
public Data() {
this.dataMap = new HashMap();
}
public Data addToSet(String name, String key, Object value) {
Map<String, Object> map = dataMap.get(name);
if (map == null) {
map = new HashMap();
}
map.put(key, value);
dataMap.put(name, map);
return this;
}
public Map<String, Map<String, Object>> getSets() {
return dataMap;
}
public Data updateSet(String name, String key, Object value) {
return Data.this.addToSet(name, key, value);
}
public Data removeFromSet(String name, String key) {
Map<String, Object> map = dataMap.get(name);
if (map == null) {
throw new MessageException("No such property '" + key + "' for set '" + name + "'");
}
map.remove(key);
return this;
}
public Map<String, Object> getSet(String name) {
return dataMap.get(name);
}
}
public class Request {
private String method;
private String resource;
private final Map<String, Object> body;
private final Map<String, String> headers;
private final Map<String, String[]> parameters;
public Request() {
this.body = new HashMap();
this.headers = new HashMap();
this.parameters = new HashMap();
}
public String getMethod() {
return Objects.toString(method, "");
}
public String getResource() {
return Objects.toString(resource, "");
}
public Map<String, Object> getBody() {
return body;
}
public Map<String, String> getHeaders() {
return headers;
}
public Map<String, String[]> getParameters() {
return parameters;
}
public String getHeader(String name) {
return headers.get(name);
}
public Request setBody(String payload) {
try {
this.body.putAll(new ObjectMapper().readValue(payload, new TypeReference<Map<String, Object>>() {
}));
return this;
} catch (JsonProcessingException ex) {
throw new MessageException(ex);
}
}
public Request setMethod(String name) {
this.method = name;
return this;
}
public Request setResource(String name) {
this.resource = name;
return this;
}
public Request setHeaders(Map<String, String> headers) {
this.headers.putAll(headers);
return this;
}
public Request setParameters(Map<String, String[]> parameters) {
this.parameters.putAll(parameters);
return this;
}
}
public class Response {
private String code;
private String data;
private String messageId;
private String timestamp;
private String description;
public Response() {
}
public String getCode() {
return Objects.toString(code, "");
}
public String getData() {
return Objects.toString(data, "");
}
public String getMessageId() {
return Objects.toString(messageId, "");
}
public String getTimestamp() {
return Objects.toString(timestamp, "");
}
public String getDescription() {
return Objects.toString(description, "");
}
public Response setCode(String code) {
this.code = code;
return this;
}
public Response setData(String data) {
this.data = data;
return this;
}
public Response setMessageId(String messageId) {
this.messageId = messageId;
return this;
}
public Response setTimestamp(String timestamp) {
this.timestamp = timestamp;
return this;
}
public Response setDescription(String description) {
this.description = description;
return this;
}
}
当序列化为json时,我会得到一个有效的字符串
{
"request": {
"headers": {},
"method": "",
"resource": "",
"body": {
"whatsapp": {
"conversationId": "39f09c41-1bd3-4e81-b829-babed3747d4b",
"name": "Dave",
"source": "+123456789098"
},
"payment": {
"product": "chocolate",
"amount": 1,
"method": "cashapp",
"msisdn": "123456789098",
"entity": "The Fudge Shop"
}
},
"parameters": {}
},
"data": {
"sets": {
"whatsapp": {
"provider": "clickatell",
"name": "Dave",
"destination": "123456789098",
"source": "123456789098",
"message": "Your payment of $1.00 received, your receipt.no is QWJ124XPA9."
},
"cashapp": {
"amount": 1,
"receiptNo": "QWJ124XPA9",
"name": "Dave Chapelle",
"msisdn": "123456789098"
}
}
},
"response": {
"code": "202",
"data": "",
"messageId": "20210623160202a647d32ee9ae477f9c90d8b1fbfd763a",
"description": "Processing Request",
"timestamp": "2021-06-23 16:02:02.408"
}
}
当我尝试将json反序列化回pojo时
Message output = new ObjectMapper().readValue(json.toString(), Message.class);
我得到一个错误:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_OBJECT token
尝试反序列化Map<String, Object>
正文时,似乎从请求类生成了错误:
如何正确反序列化地图
# 1 楼答案
对于字符串问题,以下来源可能会有所帮助:
Can not deserialize instance of java.lang.String out of START_OBJECT token
https://www.baeldung.com/jackson-map#1-mapltstring-stringgt-deserialization
为什么此代码无法工作
杰克逊并不比你强大多少
如果Jackson获取要序列化的对象,它将尝试序列化其所有值。而且只有它的值(这对于独立于类是非常好的)。这是一个json对象:
现在,这个对象的类是什么?它可能是
Fruit.class
、Image.class
甚至RoundObject.class
,json不知道,Jackson也不知道那么json如何发现类是什么呢?通过查看对象引用的类型。在你的情况下,它是对象。在对象中。类,Jackson找不到需要已保存对象的变量的构造函数,因此它崩溃
解决方案
尝试序列化对象不是一个好主意。如果您想要放入非常不同的类,例如
Apple
和Banana
,则创建一个名为interface
或abstract class
的Fruit
的类,这两个类都实现。现在,在此类顶部使用此注释:以及使用地图<;水果串>;应该有用
# 2 楼答案
对我有效的解决方案是使用自定义反序列化、
@JsonDeserialize
注释&JsonDeserializer
接口,以实现所需的结果以下是解决方案:
# 3 楼答案
试试这个JacksonUtils
这是完整的代码片段:
如果您想使用immutable对象,那么它是另一种模型配置,但是
main
类中的代码将是相同的