How to inject the key of each map entry into the corresponding value object with Jackson deserialization?

时间:2016-02-12 20:16:01

标签: java json jackson

I have the following json object.

<?php
function underline($page) {
    if (strpos($_SERVER['REQUEST_URI'], $page) !== false) {
        echo "underline";
    }
}
?>

<div class="navigation>
<a href="index.php" class="<?php underline('index.php'); ?>">Home<a> <!-- simulating that the user is on this page -->
<a href="about.php" class="<?php underline('about.php'); ?>">About me</a>
<a href="contact.php" class="<?php underline('contact.php'); ?>">Contact me!</a>
</div>

and I want to map this json object to the following java object.

{
  "items": {
    "item-1": {"type":"A", "desc": "blabla"},
    "item-2": {"type":"B", "desc": "blabla"},
    ...
  }
}

The deserialization works only when I provide the following json object.

public class MyObject {
  private final Map<String,Item> items;

  @JsonCreator
  public MyObject(@JsonProperty Map<String,Item> items) { ... }
  ...
}

class Item {
  private final string id;             <-- ideally could be initialized by the corresponding key in the map
  private final String type;
  private final String desc;

  public Item(@JsonProperty String id, @JsonProperty String type, @JsonProperty String desc) { ... }
}

That's not ideal (ie: redundancy -> error prone).

Is there a jackson annotation to solve this common pattern, or some other way? I failed to find something like { "items": { "item-1": {"id":"item-1", "type":"A", "desc": "blabla"}, "item-2": {"id":"item-2", "type":"B", "desc": "blabla"}, ... } } .

Update: I'm not interested by a solution where the id argument of the constructor is initialized to null.

2 个答案:

答案 0 :(得分:0)

.hovereffect:hover:after { opacity: 1; }

It deserialises the json and if you will not provide the value of id then default it would be null.

答案 1 :(得分:0)

我找到了一个解决方案,涉及一个自定义反序列化器。这里没有真正的魔法(没有方便的注释),但也许它会有所帮助。

@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;   // Fills the key in the value object!

        return user;
    }
}