wonza
wonza

Reputation: 302

Deserialize JSON in Jackson where key is a value

{
  {
      "1234": {
          "name": "bob"
      }
  },
  {
      "5678": {
          "name": "dan"
      }
  }
}

I have a class representing name (and other fields, I've just made it simple for this question). But the each element is key'd with the id of the person.

I've tried several things including:

class Name {
     String Name;
     //getter and setter
}
class NameId {
     String id;
     Name name;
     //getter and setters
}

//json is the string containing of the above json
ArrayList<NameId> map = objectMapper.readValue(json, ArrayList.class);
for (Object m : map) {
    LinkedHashMap<String, NameId> l = (LinkedHashMap)m;
            Map<String, NameId> value = (Map<String, NameId>) l;

            //System.out.println(l);
            //System.out.println(value);
            for (Object key : value.keySet()) {
                System.out.println("key: " + key);
                System.out.println("obj: " + value.get(key));

                NameId nameId = (NameId)value.get(key);

            }
}

The problem I have is it doesn't allow that cast to NameId. The error I get is:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to NameId

Any ideas on the best way to parse such a json string like this properly?

Upvotes: 0

Views: 5649

Answers (4)

user3335083
user3335083

Reputation:

no custom deserializer needed.

first, the json file as @klaimmore suggested (named test.json):

{
    "1234": {
        "name": "bob"
    },
    "5678": {
        "name": "dan"
    }
}

Secondly. here's the 2 separate class files:

@JsonDeserialize
public class Name {
    String name;

    public Name(String name) {
        this.name = name;
    }
    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }
}

and

@JsonDeserialize
public class NameId {
    Name name;
    String id;
    /**
     * @return the id
     */
    public String getId() {
        return id;
    }
    /**
     * @param id the id to set
     */
    public void setId(String id) {
        this.id = id;
    }
    /**
     * @return the name
     */
    public Name getName() {
        return name;
    }
    /**
     * @param name the name to set
     */
    public void setName(Name name) {
        this.name = name;
    }
}

and the extra simple json parser class.

public class JsonParser {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {

        String jsonString = new String(Files.readAllBytes(Paths.get("test.json")));
        ObjectMapper mapper = new ObjectMapper();
        Map<String,NameId> nameIdList = mapper.readValue(jsonString, new TypeReference<Map<String,NameId>>(){});
        nameIdList.entrySet().forEach(nameIdEntry -> System.out.println("name id is: " + nameIdEntry.getKey() + 
                " and name is: " + nameIdEntry.getValue().getName().getName()));

    }

}

also. this is pretty much a dupe of How to convert json string to list of java objects. you should read this.

Upvotes: 0

geco17
geco17

Reputation: 5294

Your json is malformed. You need the square brackets around it otherwise it isn't considered a json array. If your json looks like (for example)

[
    {
        "1234" : {
            "name" : "dan"
        }
    },
    {
        "5678" : {
            "name" : "mike"
        }
    }
]

you can write a custom deserializer for the object mapper. See the working example below:

public static void main(String... args) throws Exception {
    String testJson = "[{ \"1234\" : { \"name\" : \"dan\" } },{ \"5678\" : { \"name\" : \"mike\" } }]";

    ObjectMapper mapper = new ObjectMapper();
    SimpleModule module = new SimpleModule();
    module.addDeserializer(NameId.class, new MyDeserializer());
    mapper.registerModule(module);
    ArrayList<NameId> map = mapper.readValue(testJson.getBytes(), new TypeReference<List<NameId>>() {
    });
    for (NameId m : map) {
        System.out.println(m.id);
        System.out.println(m.name.name);
        System.out.println("----");
    }
}


@JsonDeserialize(contentUsing = MyDeserializer.class)
static class NameId {
     String id;
     Name name;
     //getter and setters
    }

static class Name {
     String name;
     //getter and setter
}

static class MyDeserializer extends JsonDeserializer<NameId> {

    @Override
    public NameId deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        JsonNode node = p.getCodec().readTree(p);
        Map.Entry<String, JsonNode> nodeData = node.fields().next();
        String id = nodeData.getKey();
        String name = nodeData.getValue().get("name").asText();
        Name nameObj = new Name();
        nameObj.name = name;
        NameId nameIdObj = new NameId();
        nameIdObj.name = nameObj;
        nameIdObj.id = id;
        return nameIdObj;
    }
}

Upvotes: 1

Klaimmore
Klaimmore

Reputation: 690

Your json is not valid. Maybe a little bit different:

{
    "1234": {
        "name": "bob"
    },
    "5678": {
        "name": "dan"
    }
}

And you could model something like:

class Person {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

And instead of attemping to use a list, use a map:

Map<Integer, Person> map = new ObjectMapper().readValue(json,
    TypeFactory.defaultInstance()
            .constructMapType(Map.class, Integer.class, Person.class));

Upvotes: 0

Md.ibrahim khalil
Md.ibrahim khalil

Reputation: 479

try this

Iterator<String> iterator1 =outerObject.keys();
while(iterator1.hasNext())
{
JsonObject innerObject=outerObject.getJsonObject(iterator1.next());
Iterator<String> iterator2=innerObject.keys();
while(iterator2.hasNext()){
String name=innerObject.getString(iterator2.next());
}
} 

Upvotes: 0

Related Questions