【问题标题】:Jackson/GSON: Apply Map to POJOJackson/GSON:将地图应用于 POJO
【发布时间】:2015-06-23 14:11:07
【问题描述】:

假设我有一个包含很多字段的 POJO。我还有一张带有一堆属性的地图,这些属性可以很好地映射到 POJO 中的字段。现在我想将地图中的属性应用到我的 POJO。我该怎么做?

Jackson 提供了方法new ObjectMapper().convertValue(),但这会创建一个新的 POJO 实例。我真的必须这样做吗?

om = new ObjectMapper();
pojoMap = om.convertValue(pojo, Map.class);
pojoMap.putAll(properties);
pojo = om.convertValue(pojoMap, Pojo.class);

没有更简单的方法吗?

由于我没有使用 GSON 的经验,而且我们这里也有它,我该如何使用 GSON?

【问题讨论】:

  • jsonschema2pojo.org 对您有帮助吗?这是根据您的 JSON 或 JSON 模式生成 pojo
  • @Karoly 我已经有了我的 POJO 课程。 JSON 只是 Jackson 的一个副作用,但我这里没有用到。
  • 这个地图是json属性还是为什么要用json库?
  • @OskarKjellin 好吧,基本上我对 Jackson 有经验,因为它有 convertValue(),我认为这足以解决我的问题...... :)

标签: java jackson gson deserialization


【解决方案1】:

是的,您可以使用 ObjectMapper 的 readerForUpdating 方法创建一个 ObjectReader,它将从根 JSON 对象更新现有实例,而不是实例化一个新实例:

@Test
public void apply_json_to_existing_object() throws Exception {
    ExampleRecord record = new ExampleRecord();
    ObjectReader reader = mapper.readerForUpdating(record)
            .with(JsonParser.Feature.ALLOW_SINGLE_QUOTES)
            .with(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES);
    reader.readValue("{ firstProperty: 'foo' }");
    reader.readValue("{ secondProperty: 'bar' }");
    assertThat(record.firstProperty, equalTo("foo"));
    assertThat(record.secondProperty, equalTo("bar"));
}

public static class ExampleRecord {
    public String firstProperty;
    public String secondProperty;
}

您还可以从现有的ObjectReader 创建一个价值更新阅读器。以下声明似乎等效:

    ObjectReader reader = mapper.reader(ExampleRecord.class)
            .withValueToUpdate(record)
            .with(/* features etc */);

加法

不过,以上内容并没有真正回答您的问题。

由于您没有想要以 JSON 形式对记录进行更改,而是以地图形式进行更改,因此您必须进行一些修改,以便杰克逊能够读取您的地图。您不能直接执行此操作,但您可以将“JSON”写入令牌缓冲区,然后将其读回:

@Test
public void apply_map_to_existing_object_via_json() throws Exception {
    ExampleRecord record = new ExampleRecord();
    Map<String, Object> properties = ImmutableMap.of("firstProperty", "foo", "secondProperty", "bar");

    TokenBuffer buffer = new TokenBuffer(mapper, false);
    mapper.writeValue(buffer, properties);
    mapper.readerForUpdating(record).readValue(buffer.asParser());

    assertThat(record.firstProperty, equalTo("foo"));
    assertThat(record.secondProperty, equalTo("bar"));
}

(顺便说一句,如果这看起来很费力,序列化到令牌缓冲区并再次反序列化实际上是 ObjectMapper.convertValue 的实现方式,因此功能上的变化并不大)

【讨论】:

  • 我在玩BeanUtils 并注意到它无法自动转换为枚举。杰克逊可以 :) 无论如何,感谢您将我指向readerForUpdating()。但是,我不知道您为什么使用TokenBuffer。我用objectMapper.readerForUpdating(pojo).readValue(objectMapper.writeValueAsString(properties)); 还是这样不好?
  • @sjngm:使用 TokenBuffer 可能更有效,因为可以跳过编写 JSON 字符串的一些细节(例如,将数字转换为字符串,将整个对象组合成单个字符串)。不过,它不应该对功能产生任何影响。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-07-24
  • 1970-01-01
  • 1970-01-01
  • 2020-06-04
  • 1970-01-01
  • 2021-01-14
  • 1970-01-01
相关资源
最近更新 更多