Skip to content

Partial deserialization with POJOs, but requires full reserialization #549

Closed
@fabienrenaud

Description

@fabienrenaud

Hi,

I have a JSON blob I have no idea what its content that might be. It comes from some database and other scripts may change (delete, create, update) lots of keys/objects/arrays at any depth any time.

However, my java job still needs to read that huge and mysterious blob and update a fragment of it.
Problem is that i'd still like to do that with POJOs. But if I use POJOs, data gets loss while converting to the POJO.

Hereafter is a full executable example:

package test;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;

public class JsonPojo {

    static final String JSON_INPUT = "{"
            + "\"a1\":{\"b1\":\"value_b1\",\"c1\":\"value_c2\"},"
            + "\"a2\":{\"b2\":\"value_b2\",\"c2\":\"value_c2\"},"
            + "\"a3\":{\"b3\":\"value_b3\",\"c3\":\"value_c3\"}"
            + "}";
    static final String JSON_OUTPUT = "{"
            + "\"a1\":{\"b1\":\"value_b1\",\"c1\":\"value_c2\"},"
            + "\"a2\":{\"b2\":\"value_b2\",\"c2\":\"hello\"},"
            + "\"a3\":{\"b3\":\"value_b3\",\"c3\":\"value_c3\"}"
            + "}";

    public static void main(String[] args) throws IOException {
        new JsonPojo().run();
    }

    void run() throws IOException {
        runWithTree();
        runWithPojo();
    }

    void runWithTree() throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
        JsonNode node = mapper.readTree(JSON_INPUT);
        ((ObjectNode) node.get("a2")).put("c2", "hello");
        String output = mapper.writeValueAsString(node);
        if (JSON_OUTPUT.equals(output)) {
            System.out.println("runWithTree: OK");
        } else {
            System.out.println("runWithTree: BAD");
        }
    }

    void runWithPojo() throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); // have not choice but to use this to pass
        Pojo pojo = mapper.readValue(JSON_INPUT, Pojo.class);
        pojo.a.c = "hello";
        String output = mapper.writeValueAsString(pojo);
        if (JSON_OUTPUT.equals(output)) {
            System.out.println("runWithPojo: OK");
        } else if ("{\"a2\":{\"c2\":\"hello\"}}".equals(output)) {
            System.out.println("runWithPojo: BAD BUT EXPECTED");
        } else {
            System.out.println("runWithPojo: VERY BAD");
        }
    }

    static class Pojo {

        @JsonProperty("a2")
        private PojoA a;
    }

    static class PojoA {

        @JsonProperty("c2")
        private String c;
    }
}

Note: JSON_INPUT is extremely simplified and there are no patterns of any kind in the real blobs.

Questions:

  1. Is that feature already supported by databind or some other module?
  2. Could it be supported? (would consist in caching the root JsonNode and do a differential write (to note rewrite the properties that exist in the POJO).

I basically need the complementary feature of readerForUpdating, where i would update a bigger json blob with a smaller pojo.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions