1

Let's say I have a POJO with quite a few fields. I also have a map with a bunch of properties that would map nicely to fields in the POJO. Now I want to apply the properties in the map to my POJO. How can I do this?

Jackson provides method new ObjectMapper().convertValue(), but that creates a fresh instance of the POJO. Do I really have to do something like this?

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

Isn't there an easier way?

As I have no experience with GSON and we also have it lying around here, how would I do that with GSON?

sjngm
  • 12,423
  • 14
  • 84
  • 114
  • http://www.jsonschema2pojo.org/ is it help you ? this is generate the pojo based on your JSON or JSON schema – narancs Jun 23 '15 at 14:14
  • @Karoly I already have my POJO-class. JSON is just a side effect of Jackson, but I don't use it here. – sjngm Jun 23 '15 at 14:16
  • Is this map json properties or why are you using json libraries? – Oskar Kjellin Jun 23 '15 at 14:28
  • http://stackoverflow.com/questions/1432764/any-tool-for-java-object-to-object-mapping – Oskar Kjellin Jun 23 '15 at 14:29
  • @OskarKjellin Well, basically I have my experiences with Jackson and since it has `convertValue()` I thought it would be enough to solve my problem... :) – sjngm Jun 23 '15 at 14:38
  • if you can choose between POJO and JSON, with GSON you can use to deserialize your Java Objects from JSON. More you can find here: [gson](https://sites.google.com/site/gson/gson-user-guide#TOC-Goals-for-Gson) – Edwin Jun 23 '15 at 14:38

1 Answers1

4

Yes, you can create an ObjectReader that will update an existing instance from the root JSON object rather than instantiating a new one, using the readerForUpdating method of ObjectMapper:

@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;
}

You can also create a value-updating reader from an existing ObjectReader. The following declaration seems equivalent:

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

Addition

The above didn't actually answer your question, though.

Since you don't have the changes you want to make to the record as JSON, but rather as a map, you have to finagle things so that Jackson will read your Map. Which you can't do directly, but you can write the "JSON" out to a token buffer and then read it back:

@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"));
}

(btw if this seems laborious, serializing to a token buffer and deserializing again is in fact how ObjectMapper.convertValue is implemented, so it's not a big change in functionality)

araqnid
  • 127,052
  • 24
  • 157
  • 134
  • I was fooling around with `BeanUtils` and noticed that it couldn't convert to enums automatically. Jackson can :) Anyway, thanks for pointing me to `readerForUpdating()`. However, I don't know why you used a `TokenBuffer`. I use `objectMapper.readerForUpdating(pojo).readValue(objectMapper.writeValueAsString(properties));` Or is this bad? – sjngm Jun 24 '15 at 11:11
  • @sjngm: using a TokenBuffer may be more efficient as some of the details of writing a JSON string can be skipped (e.g. converting numbers to strings, combining the entire object into a single string). It shouldn't make any difference to the functionality though. – araqnid Jun 24 '15 at 13:48