Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson: Keep references to keys in map values when deserializing

Tags:

java

json

jackson

I have the following JSON with a map from user IDs to user details:

{
    "users": {
        "john": { "firstName": "John", "lastName": "Doe" },
        "mark": { "firstName": "Mark", "lastName": "Smith" }
    }
}

and I'm using the following code to deserialize the JSON into a Java objects:

class User {
    public String userID;

    public String firstName;
    public String lastName;
}

public class Users {
    public Map<String, User> users;

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        Reader source = Files.newBufferedReader(Paths.get("test.json"));
        Users all = mapper.readValue(source, Users.class);
        // ...
    }
}

After the deserialization, I want the field User.userID to be set to the corresponding key in the users map.

For example all.users.get("john").userID should be "john".

How can I do that?

like image 1000
eminescu Avatar asked Oct 29 '22 10:10

eminescu


1 Answers

Create a custom deserializer for User object and use this for the Map. Here's a full example:

@Test
public void test() throws JsonParseException, JsonMappingException, IOException {
    ObjectMapper mapper = new ObjectMapper();

    Data data = mapper.readValue("{\"users\": {\"John\": {\"id\": 20}, \"Pete\": {\"id\": 30}}}", Data.class);

    assertEquals(20, data.users.get("John").id);
    assertEquals(30, data.users.get("Pete").id);
    assertEquals("John", data.users.get("John").name);
    assertEquals("Pete", data.users.get("Pete").name);
}

public static class Data {
    @JsonDeserialize(contentUsing = Deser.class)
    public Map<String, User> users;
}

public static class User {
    public String name;
    public int id;
}

public static class Deser extends JsonDeserializer<User> {

    @Override
    public User deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        String name = ctxt.getParser().getCurrentName();

        User user = p.readValueAs(User.class);

        user.name = name;  // This copies the key name to the user object

        return user;
    }
}
like image 89
john16384 Avatar answered Nov 15 '22 06:11

john16384