2

I've a JSON with duplicate keys as shown below.

    {
        "name": "Test",
        "attributes": [{
            "attributeName": "One",
            "attributeName": "Two",
            "attributeName": "Three"
        }]
    }

When I transform it to a Map<String, Object> using Jackson, it's transformed as shown below.

{name=Test, attributes=[{attributeName=Three}]}

The value of last occurrence of attribute name is considered. Is there a way to tell Jackson to represent it as a Multimap instead? I am ok to use any implementation of Multimap. My current code is as shown below:

import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

public class TestJSON {

    public static void main(String[] args) throws Exception{
        ObjectMapper mapper = new ObjectMapper();
        String json = "{\"name\": \"Test\",\"attributes\": [{\"attributeName\": \"One\",\"attributeName\": \"Two\",\"attributeName\": \"Three\"}]}";
        Map<String, Object> map = new HashMap<>();
        map = mapper.readValue(json, new TypeReference<Map<String, Object>>(){});
        System.out.println(map);
    }

}
JSN
  • 2,035
  • 13
  • 27
  • How about fixing the JSON, and make it valid, instead? See https://stackoverflow.com/questions/5306741/do-json-keys-need-to-be-unique – JB Nizet Jul 03 '17 at 14:19

1 Answers1

0

Don't think that Jackson will handle it in his native way, but you can wrap this JSON to simple POJO and get Multimap out of it. Example:

public class Attribute {
    private String attributeName;

    // getter and setter here
}

public class AttributeContainer {
    private String name;
    private List<Attribute> attributes;

    public Multimap<String, String> getAttributeMultiMap() {
      ImmutableMultimap.Builder<String, String> builder = ImmutableMultimap.builder();
          for (Attribute attribute : attributes) {
             builder.put("attributeName", attribute.getAttributeName())
          }
       return builder.build();
    }

    // getters and setters here
}

public void main(String[] args) {
    ObjectMapper mapper = new ObjectMapper();
    String json = "{\"name\": \"Test\",\"attributes\": [{\"attributeName\": \"One\",\"attributeName\": \"Two\",\"attributeName\": \"Three\"}]}";
    AttributeContainer attributeContainer;
    attributeContainer = mapper.readValue(json, new TypeReference<AttributeContainer>(){});

    System.out.println(attributeContainer.getAttributeMultiMap());
}
rxn1d
  • 1,236
  • 6
  • 18
  • May I know which implementation of Multimap you're using? – JSN Jul 03 '17 at 13:54
  • Sure, it is [guava](https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/ImmutableMultimap.html#builder()) – rxn1d Jul 03 '17 at 13:55
  • I've problems in constructing Multimap. May I know which version of guava you are using? – JSN Jul 03 '17 at 14:13
  • @Beginner: Did you remember to register the Guava module on your `ObjectMapper` instance? Jackson will not understand Guava without it. – Henrik Aasted Sørensen Jul 03 '17 at 14:32
  • @Beginer sory, I had a bad code in example, and now it's good. Corrent way to construct builder - `ImmutableMultimap.Builder builder = ImmutableMultimap.builder();` post was updated. – rxn1d Jul 03 '17 at 14:39
  • I tried your code and get this as output : `{attributeName=[Three]}` – JSN Jul 04 '17 at 14:03
  • @Beginer You are right. I missed fact that you basically has very tricky JSON format. Is it possible to change it to something like: `"{\"name\": \"Test\",\"attributes\": [{\"attributeName\": \"One\"},{\"attributeName\": \"Two\"},{\"attributeName\": \"Three\"}]}"` (wrap every `"attributeName": "Value" to object`) ? – rxn1d Jul 04 '17 at 14:30