如何使用jackson(Java)反序列化对象中的json对象?
Posted
技术标签:
【中文标题】如何使用jackson(Java)反序列化对象中的json对象?【英文标题】:How to deserialize json Object in Object with jackson(Java)? 【发布时间】:2019-12-01 13:54:13 【问题描述】:如何使用 jackson(Java) 在 Object 中反序列化 json 对象(在我的情况下,Offer
对象存在于 current
字段中)?
输入字符串:
message.getMessage();
"header":"OFFER","message":"\"author\":\"Peter Smith\",\"previous\":null,\"current\":\"id\ ":\"eOUQieQdvB\",\"authorUserId\":\"foo\""
ObjectMapper mapper = new ObjectMapper();
PushEventMessage<PushEvent<Offer>> pushEventMessage = mapper.readValue(message.getMessage(), PushEventMessage.class);
pushEventMessage.getMessage();
"author":"Peter Smith","previous":null,"current":"id":"eOUQieQdvB","authorUserId":"foo"
PushEvent<Offer> pushEvent = mapper.readValue(pushEventMessage.getMessage(), PushEvent.class);
pushEvent.getAuthor(); // is OK and contain "Peter Smith"
pushEvent.getCurrent() // is KO and contain id=eOUQieQdvB, authorUserId=foo
我要反序列化:
Offer offer= mapper.readValue(pushEvent.getCurrent() + "", Offer.class);
我的错误是:
com.fasterxml.jackson.core.JsonParseException: Unexpected character ('i' (code 105)): was expecting double-quote to start field name
at [Source: (String)"id=eOUQieQdvB, authorUserId=foo,
EDIT 1,我添加PushEvent<T>
类。
import lombok.*;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class PushEvent<T>
String author;
T previous;
T current;
String error;
EDIT 2,我试试这个,但结果是一样的
PushEvent<Offer> pushEvent = mapper.readValue(pushEventMessage.getMessage().replaceAll("\\\"", "\""), PushEvent.class);
我采用@Smutje 的解决方案,这解决了第一个问题。!!
编辑 3,我在 Offer
对象中有一个 java.time.ZonedDateTime
。
"author":"Peter Smith","previous":null,"current":"id":"00Yno9WwsL","authorUserId":"foo","createdAt":"offset": "totalSeconds":0,"id":"Z","rules":"transitionRules":[],"transitions":[],"fixedOffset":true,"zone":"id": "UTC","rules":"transitionRules":[],"transitions":[],"fixedOffset":true,"dayOfMonth":11,"dayOfWeek":"SUNDAY","dayOfYear":42 ,"月":"二月","年":2018,"小时":1,"分钟":0,"纳米":0,"秒":0,"月值":2,"年表": "id":"ISO","calendarType":"iso8601"
我有这个错误:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.ZonedDateTime` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (String)""id":"00Yno9WwsL","authorUserId":"foo", ....."createdAt":"offset":"totalSeconds":0,...
EDIT 4,我添加Offer
类。
@Slf4j
@Data
@NoArgsConstructor
public class Offer
@Id
protected String id;
protected String authorUserId;
protected ZonedDateTime createdAt;
【问题讨论】:
pushEvent.getCurrent()
有什么返回类型?
为什么不用另一个 POJO?无法反序列化为Offer
,因为它没有id
,还有剩余字段,你能显示Offer
类吗?
@Smutje,在我的例子中是 LinkedHashMap,因为所有双引号都被撤销(我不知道为什么?)我想要一个对象“Offer”。
请添加您的“PushEvent”类。
@Smutje,我用PushEvent<T>
class 编辑了我的问题。
【参考方案1】:
由于许多映射框架无法使用泛型或继承层次结构正确反序列化对象,因此以下是丑陋的,但应该是可能的
PushEvent<Offer> pushEvent = mapper.readValue(pushEventMessage.getMessage(), PushEvent.class);
String serializedOffer = mapper.writeValueAsString(pushEventMessage.getCurrent());
Offer offer = mapper.readValue(serializedOffer, Offer.class);
pushEvent.setCurrent(offer);
说明:Jackson 将您的内部对象反序列化不是您所说的 Offer
,而是作为 LinkedHashMap
在将 JSON 对象读取为实际 Offer
之前再次序列化为 JSON 对象。
您尝试将LinkedHashMap
读入Offer
失败,因为您(隐含地)使用LinkedHashMap
的toString
表示来解析不 生成有效JSON 的哪个。 p>
编辑 4 答案:,如果 Object 包含 ZonedDateTime
。读写时使用:
ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());
mapper.setDateFormat(new StdDateFormat());
【讨论】:
谢谢,我还有最后一个问题。我的 Offer 对象包含 ZonedDateTime \"createdAt\":\"offset\":\"totalSeconds\":0,\"id\":\"Z\",\"rules\":\ "transitionRules\":[],\"transitions\":[],\"fixedOffset\":true,\"zone\":\"id\":\"UTC\",\"rules\ ":\"transitionRules\":[],\"transitions\":[],\"fixedOffset\":true,\"dayOfMonth\":11,\"dayOfWeek\":\"SUNDAY\" ,\"dayOfYear\":42,\"month\":\"FEBRUARY\",\"year\":2018,\"hour\":1,\"minute\":0,\"nano\" :0,\"second\":0,\"monthValue\":2,\"chronology\":\"id\":\"ISO\",\"calendarType\":\"iso8601\" 请扩展您的问题,cmets 不适合长行代码 com.fasterxml.jackson.databind.exc.InvalidDefinitionException: 无法构造java.time.ZonedDateTime
的实例(没有创建者,如默认构造,存在):无法从对象值反序列化(没有委托或属性-基于创建者)在 [Source: (String)""id":"00Yno9WwsL","authorUserId":"foo", ....."createdAt":"offset":"totalSeconds":0,. ..
简而言之:忽略反序列化字段并手动填充它与您的序列化策略相反。【参考方案2】:
错误消息告诉您问题出在哪里:“期望用双引号来开始字段名称”。
通过简单检查,您读取 json 字符串的代码看起来是正确的,因此请确保您提供的数据有效。
提示:您可以通过简单地序列化演示对象来生成已知良好的数据:
new ObjectMapper().writeValueAsString(demoObject);
然后您可以尝试使用该字符串运行您的代码,这将告诉您您的输入是否有效。
【讨论】:
以上是关于如何使用jackson(Java)反序列化对象中的json对象?的主要内容,如果未能解决你的问题,请参考以下文章
Java Jackson json 到对象反序列化。如何处理 OWASP 不安全的反序列化?
如何使用 Jackson 解析 JSON 数组项中的原始值?
如何使用 Jackson 反序列化来自 json 对象的对象数组