定制杰克逊反序列化器和阵列

时间:2018-01-18 03:16:21

标签: json spring-boot jackson deserialization

请注意:此网站上有很多关于如何使用自定义杰克逊反序列化程序的问题......这个问题不是还有一个问题!这个问题与在非常独特的情况下使用反序列化器有关(在本网站上没有任何问题/答案!)。

Spring Boot使用Jackson进行JSON序列化。我有两个POJO在@RequestBody(HTTP请求实体)中用于POST端点:

@JsonDeserialize(using = FizzDeserializer.class)
public class Fizz {
  private String name;
  private String label;
  private Integer code;

  // Getters, setters & ctors
}

@JsonDeserialize(using = BuzzDeserializer.class)
public class Buzz {
  private String id;
  private String locale;
  private Set<Fizz> fizzes;

  // Getters, setters & ctors
}

@RestController
@RequestMapping("v1/data/buzzes")
public class BuzzController {
  @PostMapping
  public void updateBuzz(@RequestBody Buzz buzz) {
    // do whatever
  }
}

我希望HTTP客户端能够将以下JSON发布到此端点:

{
  "id" : "12345-67890",
  "locale" : "en_US",
  "fizzes" : [
    "foo",
    "bar"
  ]
}

...其中"foo"和“bar”是两个不同Fizz#names个实例的Fizz。换句话说,我不希望客户端必须指定整个 Fizz对象,只需将其name指定为JSON字符串(我的app + DB保证Fizzes有独特的名字。)

所以我使用自定义JsonDeserializer来完成所有这些映射:

public BuzzDeserializer extends JsonDeserializer<Buzz> {
  Buzz deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
    JsonNode buzzNode = jsonParser.readValueAsTree();

    String id = buzzNode.get("id");
    String locale = buzzNode.get("locale");

    // TODO: How to read "foo" and "bar" (etc.) into a Set<Fizz> instances?
    Set<Fizz> fizzes = ???

    new Buzz(id, locale, fizzes);
  }
}

public FizzDeserializer extends JsonDeserializer<Fizz> {
  private FizzDAO fizzDAO;

  // Getters, setters & ctors...

  Fizz deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
    JsonNode fizzNode = jsonParser.readValueAsTree();

    // If I can get access to "foo"/"bar"/etc. string somehow, I can look up the Fizz using the DAO:
    String fooBarEtcStr = ???

    return fizzDAO.findFizzByName(fooBarEtcStr);
  }    

但是我不确定如何将JSON fizzes数组读入此反序列化器中的Set<Fizz>有什么想法吗?

1 个答案:

答案 0 :(得分:1)

从对问题的评论中得出,唯一的问题似乎是获取JSON数组。如果要在序列化程序中注入或提供要查找的服务或DAO,请尝试以下方法:

final JsonNode arr = buzzNode.get("fizzes");

if (arr.isArray()) {
    final Set<Fizz> fizzes = Sets.newHashSetWithExpectedSize(arr.size());
    for (JsonNode obj : arr) {
        final String name = obj.asText();
        Fizz fizz = // load from DAO
        fizzes.add(fizz);
    }
}

这当然可以通过收集String值并仅使用一个DAO来优化。还有一些java8流可以使代码更简洁。