Json 自定义Jackson反序列化程序和数组

Json 自定义Jackson反序列化程序和数组,json,spring-boot,jackson,deserialization,Json,Spring Boot,Jackson,Deserialization,请注意:在这个网站上有很多关于如何使用自定义Jackson反序列化程序的问题…这个问题不是其中的一个!这些问题与在非常特殊的情况下使用反序列化程序有关,在此网站上没有任何问题/答案 这里使用Jackson进行JSON序列化的Spring引导。我有两个POJO,它们在@RequestBody HTTP请求实体中用于POST端点: @JsonDeserialize(using = FizzDeserializer.class) public class Fizz { private String

请注意:在这个网站上有很多关于如何使用自定义Jackson反序列化程序的问题…这个问题不是其中的一个!这些问题与在非常特殊的情况下使用反序列化程序有关,在此网站上没有任何问题/答案

这里使用Jackson进行JSON序列化的Spring引导。我有两个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
  }
}
{
  "id" : "12345-67890",
  "locale" : "en_US",
  "fizzes" : [
    "foo",
    "bar"
  ]
}
…其中foo和bar是两个不同的Fizz实例的fizzname。换句话说,我不希望客户端必须指定整个Fizz对象,只需将其名称指定为JSON字符串my 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数组读入这个反序列化器中的集合。有什么想法吗?

根据对问题的评论,唯一的问题似乎是获取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);
    }
}

当然,这可以通过收集字符串值并只使用一个DAO调用来优化。另外,一些java8流可以减少代码的冗余。

显然,您需要在反序列化程序中注入一个服务/DAO来按名称加载Fizzes。这里有一个关于如何进行的问题:是的,谢谢@msparer+1这正是我所做的,你看过上面的代码了吗?问题是如何将字符串名[foo,bar]的JSON数组解析到列表中。然后,我可以将该列表中的每个字符串传递到DAO中,以查找其各自的嘶嘶声。