Jackson:反序列化时保留对映射值中键的引用

emi*_*scu 5 java json jackson

我有以下 JSON,其中包含从用户 ID 到用户详细信息的映射:

{
    "users": {
        "john": { "firstName": "John", "lastName": "Doe" },
        "mark": { "firstName": "Mark", "lastName": "Smith" }
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在使用以下代码将 JSON 反序列化为 Java 对象:

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);
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

反序列化后,我希望将字段User.userID设置为users映射中的相应键。

例如all.users.get("john").userID应该是"john".

我怎样才能做到这一点?

joh*_*384 2

为 User 对象创建一个自定义反序列化器并将其用于 Map。这是一个完整的示例:

@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;
    }
}
Run Code Online (Sandbox Code Playgroud)