【问题标题】:How to deserialize json Object in Object with jackson(Java)?如何使用jackson(Java)反序列化对象中的json对象?
【发布时间】: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&lt;T&gt; 类。

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&lt;T&gt; class 编辑了我的问题。

标签: java json jackson


【解决方案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 失败,因为您(隐含地)使用LinkedHashMaptoString 表示来解析 生成有效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);

然后您可以尝试使用该字符串运行您的代码,这将告诉您您的输入是否有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-12
    • 1970-01-01
    • 1970-01-01
    • 2019-02-07
    • 2021-05-20
    • 2020-07-21
    • 1970-01-01
    • 2020-08-07
    相关资源
    最近更新 更多