Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson JSON serialization in Java - write k/v pairs to root instead of nested in property name

I need to write a JSON string that follows this basic format:

{ 
    "xmlns": {
       "nskey1" : "nsurl1",
       "nskey2" : "nsurl2"
    },

    "datakey1": "datavalue1",
    "datakey2": "datavalue2"
}

I'm using the following class to present the data, and an instance of this class is serialized with the Jackson ObjectMapper.

public class PayloadData {
    public Map<String, String> payloadData = new TreeMap<String, String>();

    @JsonProperty("xmlns")
    public Map<NamespaceEnum, String> namespaces = new TreeMap<NamespaceEnum, String>();

    @JsonAnyGetter
    public Map<String, String> getPayloadData() {
        return payloadData;
    }
}

If I serialize an instance of this class as-is, the resulting JSON will be something like this:

{ 
    "xmlns": {
       "nskey1" : "nsurl1",
       "nskey2" : "nsurl2"
    },
    "payloadData": {
        "datakey1": "datavalue1",
        "datakey2": "datavalue2"
    },

    "datakey1": "datavalue1",
    "datakey2": "datavalue2"
}

That makes sense based on the naming conventions, but I'm looking for a method to have the payloadData map placed in the JSON's root context without the duplicate that contains the property identifier and nesting. I've tried a lot of annotations in various forms; I've tried disabling the ObjectMapper wrap_root_value SerializationFeature; I honestly feel like I've tried just about everything. So before I throw a computer out the window, I'm asking for a second (and beyond) set of eyes to help point out what must be painfully obvious.

Thanks in advance for your attention and advice.

edit: updated the actual output JSON I see now. The data is being duplicated, and I'd like to remove the duplicate that has the nested property.

like image 661
Patrick Avatar asked Nov 23 '25 04:11

Patrick


1 Answers

The problem is that you have 2 accessors exposed for PayloadData: the public property and the getter, so it is being serialized twice. If it is possible, I would recommend restructuring your data class to be immutable. For example:

public class PayloadData {
    private final Map<String, String> payloadData;
    private final Map<NamespaceEnum, String> namespaces;

    @JsonCreator
    public PayloadData(@JsonProperty("xmlns") Map<NamespaceEnum, String> namespaces,
                       @JsonProperty("payloadData") Map<String, String> payloadData) {
        this.namespaces = namespaces;
        this.payloadData = payloadData;
    }

    @JsonAnyGetter
    public Map<String, String> getPayloadData() {
        return payloadData;
    }

    @JsonProperty("xmlns")
    public Map<NamespaceEnum, String> getNamespaces() {
        return namespaces;
    }
}

This will give you the desired output with out any configuration of the ObjectMapper.

like image 118
Sam Berry Avatar answered Nov 24 '25 18:11

Sam Berry



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!