8

I'm trying to parse json with invalid structure which has duplicate keys using Jackson library. If a json has duplicate keys, I would like to extract them as a Collection.

Example of what I'm trying to parse (the actual json that I'm trying to parse comes from Wireshark json export):

{
    "a": "a",
    "a": {
        "b": {

        },
        "b": true
    }
}

However, since this json has duplicate keys, only the last value is retained:

JsonNode tree = new ObjectMapper().readTree(json);
System.out.println(tree); // {"a":{"b":true}}

I've also tried the Guava module which has Multimap support, however it doesn't work as expected for nested json objects.

Example using Guava module for the json that I have shown before:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new GuavaModule());
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);

Multimap read = mapper.readValue(json, Multimap.class);
System.out.println(read); // {a=[a, {b=true}]}

How should I tackle this problem using Jackson library? Are there any other libraries which would support parsing of such json structure for java?

Edd
  • 1,982
  • 2
  • 21
  • 29
  • 2
    Valid JSON doesn't have duplicate keys, so a parsing library shouldn't work the way you're asking – OneCricketeer Mar 03 '17 at 07:34
  • SyntaxError: Duplicate key 'a' on line 3 – Chetan Joshi Mar 03 '17 at 08:02
  • 2
    duplicate keys is valid json. https://tools.ietf.org/html/rfc7159 "The names within an object SHOULD be unique", not required to be unique. – Justin Dennahower Feb 17 '20 at 20:42
  • 1
    @OneCricketeer I dunno. ECMA-404 (linked from json.org) says: "The JSON syntax does not impose any restrictions on the strings used as names, does not require that name strings be unique, and does not assign any significance to the ordering of name/value pairs. These are all semantic considerations that may be defined by JSON processors or in specifications defining specific uses of JSON for data interchange." – Robert Dodier Jan 25 '21 at 07:46

2 Answers2

8

If you are flexible with json library you can make use of net.sf.json.JSONObject.

This library will retain the duplicated values by storing them into arrays. If multiple same keys are available it will create one key with all the values as Array.

And also the coding part is just a single line. Once you parsed the json using net.sf.json.JSONObject then you can supply this to jackson library.

JSONObject jsonObject = JSONObject.fromObject( "{ \"a\": \"a\", \"a\": { \"b\": {},\"b\": true}}" );

System.out.println( "net.sf.json.JSONObject: " + jsonObject );

JsonNode jsonNode = new ObjectMapper().readTree( jsonObject.toString() );

System.out.println( "com.fasterxml.jackson.databind.JsonNode" + jsonNode );

Output:

net.sf.json.JSONObject: {"a":["a",{"b":[{},true]}]}
com.fasterxml.jackson.databind.JsonNode{"a":["a",{"b":[{},true]}]}

Maven dependency of net.sf.json

<dependency>
    <groupId>net.sf.json-lib</groupId>
    <artifactId>json-lib</artifactId>
    <version>2.4</version>
    <classifier>jdk15</classifier>
</dependency>
Ravi MCA
  • 2,491
  • 4
  • 20
  • 30
3

You can use "jackson" library to read the json message token by token in a streaming way, then it would not eat anything form the message.

Krzysztof Cichocki
  • 6,294
  • 1
  • 16
  • 32