Rostyslav Roshak
Rostyslav Roshak

Reputation: 4009

Java Jackson parse dynamic JSON object

What is the beast way to deal with the JSON object, that has the following structure:

{
  "Parameters": {
    "0": {
      "some key 0": "some value 0"
    },
    "1": {
      "some key 1": "some value 1"
    },
    "2": {
      "some key 2": "some value 2"
    },
    ....
    "n": {
      "some key n": "some value n"
    }
}

It contains properties from 0 to n (e.g. 100), each property is an object with single key value. Looks like all keys are different.

Is it possible to transform it into a list of Parameter, where each parameter has next structure:

public class Parameter {
    String key;
    String value;
}

What is the best way to handle this in jackson?

Upvotes: 1

Views: 2738

Answers (2)

I think Sachin's approach is the correct direction, but I would amend it in the following way, and remove some of the nested maps that it ends up with:

@JsonRootName("Parameters")
public class Parameters {
    private List<Parameter> parameters = new ArrayList<>();

    @JsonAnySetter
    public void setDynamicProperty(String _ignored, Map<String, String> map) {
        Parameter param = new Parameter();
        param.key = map.keySet().iterator().next();
        param.value = map.values().iterator().next();
        parameters.add(param);
    }

    public List<Parameter> getParameters() {
        return parameters;
    }
}

public class Parameter {
    public String key, value;
}

After deserialization, the getParameters() method will return a list of Parameter instances. Given your example input, its structure will look like this, when serialized to JSON :

[
  {
    "key": "some key 0",
    "value": "some value 0"
  },
  {
    "key": "some key 1",
    "value": "some value 1"
  },
  {
    "key": "some key 2",
    "value": "some value 2"
  },
  {
    "key": "some key n",
    "value": "some value n"
  }
]

Note that the extraction of key and value uses an iterator which will throw an exception if it encounters an empty object.

Upvotes: 1

Sachin Gupta
Sachin Gupta

Reputation: 8368

If keys are dynamic then we can use @JsonAnySetter annotation.

You can try something like this:

ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);

Parameters parameters = mapper.readValue(jsonData, Parameters.class);

Where content of Parameter class would be:

@JsonRootName("Parameters")
class Parameters {
    private List<Map<String, String>> parameters = new ArrayList<Map<String, String>>();

    @JsonAnySetter
    public void setDynamicProperty(String name, Map<String, String> map) {
        parameters.add(map);
    }

    public List<Map<String, String>> getParameters() {
        return parameters;
    }

    public void setParameters(List<Map<String, String>> parameters) {
        this.parameters = parameters;
    }

}

Upvotes: 2

Related Questions