Spring dynamically封装一个json可以是List也可以只是一个Object

jm2pwxwz  于 2024-01-05  发布在  Spring
关注(0)|答案(4)|浏览(135)

我创建了一个示例类,并响应于示例化,但这是需要修复的同一问题。响应可以是带对象的数组或just an Object。需要动态示例化

  1. public record MainClass(
  2. //the response can either be array or not array
  3. @JsonProperty("Relation") List<Relation> relation
  4. ){
  5. }
  6. public record Relation(
  7. String relation,
  8. String Id,
  9. ){
  10. }

字符串
当响应为数组Working时进行初始化
响应

  1. {
  2. "Relation": [
  3. {
  4. "url": "https://sample.com",
  5. "Id": "77"
  6. }
  7. ]
  8. }


如果响应不是数组This need to be fix,则执行初始化
响应

  1. {
  2. "Relation":{
  3. "url": "https://sample.com",
  4. "Id": "77"
  5. }
  6. }

gev0vcfq

gev0vcfq1#

另一种选择是为属性提供两个setter。

  1. public class RelationWrapper
  2. private String id;
  3. private List<Relation> relation;
  4. public void setRelation(Relation relation) {
  5. this.relation = relation == null ? null : List.of(relation);
  6. }
  7. public void setRelation(List<Relation> relation) {
  8. this.relation = relation;
  9. }
  10. public List<Relation> getRelation() {
  11. return relation;
  12. }
  13. }

字符串
这也可以用两个构造函数来完成

  1. public class RelationWrapper
  2. private final String id;
  3. private final List<Relation> relation;
  4. @ConstructorProperties({"id", "relation"})
  5. public RelationWrapper(String id, List<Relation> relation) {
  6. this.id = id;
  7. this.relation = relation;
  8. }
  9. @ConstructorProperties({"id", "relation"})
  10. public RelationWrapper(String id, Relation relation) {
  11. this.id = id;
  12. this.relation = relation == null ? null : List.of(relation);
  13. }
  14. // getters
  15. }

展开查看全部
sq1bmfud

sq1bmfud2#

我认为你需要使用JsonNode来表示值,因为它可以表示任何值(数字,字符串,数组或对象)

  1. public class RelationWrapper {
  2. private String id;
  3. private JsonNode relation;
  4. // getters & setters
  5. }
  6. public class Relation {
  7. private String id;
  8. private String url;
  9. // getters & setters
  10. }

个字符
看到

  • ObjectMapper.valueToTree(Object)
  • ObjectMapper.treeToValue(TreeNode,Class)
  • JsonNode
展开查看全部
cgfeq70w

cgfeq70w3#

你应该写自定义的std封装器,首先修改你的 Package 器来处理这两个

  1. @Data
  2. @NoArgsConstructor
  3. @AllArgsConstructor
  4. public class RelationContainer {
  5. private Relation relation;
  6. private List<Relation> relations;
  7. }

字符串
然后创建自定义std解析器:

  1. public class RelationStdDeserializer extends StdDeserializer<RelationContainer> {
  2. public RelationStdDeserializer() {
  3. super(RelationContainer.class);
  4. }
  5. @Override
  6. public RelationContainer deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
  7. var objectCodec = jsonParser.getCodec();
  8. var jsonTree = objectCodec.readTree(jsonParser);
  9. if(jsonTree instanceof NullNode){
  10. return null;
  11. } else if (jsonTree instanceof ObjectNode objectNode) {
  12. var relationNode = objectNode.get("relations");
  13. if(relationNode instanceof NullNode){
  14. return new RelationContainer(null, null);
  15. } else if (relationNode instanceof ObjectNode jsonObject) {
  16. var relation = traverseNode(jsonObject, objectCodec, new TypeReference<Relation>() {
  17. });
  18. return new RelationContainer(relation, null);
  19. } else if (relationNode instanceof ArrayNode arrayObject) {
  20. var relations = traverseNode(arrayObject, objectCodec, new TypeReference<List<Relation>>() {
  21. });
  22. return new RelationContainer(null, relations);
  23. }
  24. }
  25. throw new IOException("Failed to read relations");
  26. }
  27. private <T> T traverseNode(JsonNode jsonNode, ObjectCodec objectCodec, TypeReference<T> typeReference) throws IOException {
  28. try(var jsonParser = jsonNode.traverse(objectCodec)){
  29. return objectCodec.readValue(jsonParser, typeReference);
  30. }
  31. }
  32. }


最后在对象Map器bean中注册验证器:

  1. @Bean
  2. public ObjectMapper objectMapper(){
  3. var objectMapper = new ObjectMapper();
  4. var relationModule = new SimpleModule();
  5. relationModule.addDeserializer(RelationContainer.class, new RelationStdDeserializer());
  6. return objectMapper;
  7. }

展开查看全部
ijxebb2r

ijxebb2r4#

在Java中处理JSON数据时,您面临的问题是一个常见的问题,特别是当JSON的结构不一致时。在您的情况下,“Relation”字段可以是JSON数组或单个JSON对象。这种不一致性对数据表示提出了挑战。
您当前使用Jackson的@JsonProperty注解的方法是正确的,但需要对其进行调整以处理JSON结构中的可变性。下面是处理这种情况的最先进方法:
首先)**泛型的类型引用:**你可以使用Jackson的泛型类型引用来处理这个问题。例如,你可以尝试将类型化为List,如果失败(由于JsonProcessingException),只使用Relation再试一次。
然后)**可选 Package 器:**在某些情况下,使用Java的Optional类作为对象的 Package 器可能有助于处理JSON字段的可空性和存在性。

第一步:创建Wrapper类

  1. public class RelationWrapper {
  2. private Optional<List<Relation>> relationsList;
  3. private Optional<Relation> singleRelation;
  4. public RelationWrapper(List<Relation> relationsList) {
  5. this.relationsList = Optional.ofNullable(relationsList);
  6. this.singleRelation = Optional.empty();
  7. }
  8. public RelationWrapper(Relation singleRelation) {
  9. this.singleRelation = Optional.ofNullable(singleRelation);
  10. this.relationsList = Optional.empty();
  11. }
  12. // Getters
  13. // Setter
  14. }

字符串

第二步:实现自定义编译器

  1. public class RelationDeserializer extends JsonDeserializer<RelationWrapper> {
  2. @Override
  3. public RelationWrapper deserialize(JsonParser jsonParser, DeserializationContext ctxt)
  4. throws IOException, JsonProcessingException {
  5. JsonNode node = jsonParser.getCodec().readTree(jsonParser);
  6. try {
  7. // Attempt to deserialize as List<Relation>
  8. List<Relation> relations = jsonParser.getCodec().treeToValue(node, new TypeReference<List<Relation>>() {});
  9. return new RelationWrapper(relations);
  10. } catch (JsonProcessingException e) {
  11. // If it fails, deserialize as a single Relation object
  12. Relation relation = jsonParser.getCodec().treeToValue(node, Relation.class);
  13. return new RelationWrapper(relation);
  14. }
  15. }
  16. }

最后一步:使用自定义编译器

最后,你需要告诉Jackson在格式化Relation字段时使用这个自定义的格式化器。你可以通过在MainClass中用@JsonDeserialize注解Relation字段来做到这一点:

  1. import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
  2. import com.fasterxml.jackson.annotation.JsonProperty;
  3. public class MainClass {
  4. @JsonDeserialize(using = RelationDeserializer.class)
  5. @JsonProperty("Relation")
  6. private RelationWrapper relation;
  7. // Constructor, getters, and setters
  8. public MainClass(RelationWrapper relation) {
  9. this.relation = relation;
  10. }
  11. public RelationWrapper getRelation() {
  12. return relation;
  13. }
  14. }


该解决方案提供了一种灵活而优雅的方式来对JSON进行封装,其中特定字段的结构可能会有所不同。JSON Wrapper中的可选 Package 器可以清楚轻松地检查您是否有一个关系列表或单个关系。

展开查看全部

相关问题