【问题标题】:Jackson JSON Serialization without field name没有字段名称的杰克逊 JSON 序列化
【发布时间】:2021-06-09 19:19:43
【问题描述】:

我有一个 JAVA POJO,它有很多字段。其中一个字段是Map<String, Object>,我使用Custom JsonSerializer,因为它可以有多种类型的Objects。我只想知道如何避免fieldname 的序列化只针对这个Map<String,Object> 字段。对于 POJO 中的所有其他字段,我希望拥有字段名称,但仅出于此目的,我想将其删除。

到目前为止,当使用 Jackson searlizer 时,我得到以下输出:

{
  "isA" : "Human",
  "name" : "Batman",
  "age" : "2008",
  "others" : {
    "key1" : "value1",
    "key2" : {
      "key3" : "value3"
    },
    "key5" : {
      "key4" : "One",
      "key4" : "Two"
    }
  }
}

我想要得到以下输出:(我想要做的就是删除 Map<String,Object> 字段名称,但保留其子项。)

{
  "isA" : "Human",
  "name" : "Batman",
  "age" : "2008",
  "key1" : "value1",
  "key2" : {
    "key3" : "value3"
  },
  "key5" : {
    "key4" : "One",
    "key4" : "Two"
  }
}

下面是我的Human.class POJO,被ObjectMapper使用:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, visible = true, property = "isA")
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter
@Setter
@NoArgsConstructor
@ToString
class Human {
    private String isA;
    private String name;
    private String age;

    @JsonSerialize(using = MyCustomSearlize.class)
    private Map<String, Object> others = new HashMap<>();
}

以下是我的Custom searlizer,MAP 在搜索过程中使用它:

class MyCustomSearlize extends JsonSerializer<Map<String, Object>> {

    private static final ObjectMapper mapper = new ObjectMapper();

    @Override
    public void serialize(Map<String, Object> value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeStartObject();
        recusiveSerializer(value, gen, serializers);
        gen.writeEndObject();
    }

    public void recusiveSerializer(Map<String, Object> value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        for (Map.Entry<String, Object> extension : value.entrySet()) {
            if (extension.getValue() instanceof Map) {
                //If instance is MAP then call the recursive method
                gen.writeFieldName(extension.getKey());
                gen.writeStartObject();
                recusiveSerializer((Map) extension.getValue(), gen, serializers);
                gen.writeEndObject();
            } else if (extension.getValue() instanceof String) {
                //If instance is String directly add it to the JSON
                gen.writeStringField(extension.getKey(), (String) extension.getValue());
            } else if (extension.getValue() instanceof ArrayList) {
                //If instance if ArrayList then loop over it and add it to the JSON after calling recursive method
                for (Object dupItems : (ArrayList<Object>) extension.getValue()) {
                    if (dupItems instanceof Map) {
                        gen.writeFieldName(extension.getKey());
                        gen.writeStartObject();
                        recusiveSerializer((Map) dupItems, gen, serializers);
                        gen.writeEndObject();
                    } else {
                        gen.writeStringField(extension.getKey(), (String) dupItems);
                    }
                }
            }
        }
    }
}


下面是我的Main类:

public class Main {
    public static void main(String[] args) throws JsonProcessingException {

        Human person = new Human();

        person.setName("Batman");
        person.setAge("2008");
        Map<String, Object> others = new HashMap<>();
        others.put("key1", "value1");
        Map<String, Object> complex = new HashMap<>();
        complex.put("key3", "value3");
        others.put("key2", complex);
        Map<String, Object> complex2 = new HashMap<>();
        List<String> dup = new ArrayList<>();
        dup.add("One");
        dup.add("Two");
        complex2.put("key4", dup);
        others.put("key5", complex2);
        person.setOthers(others);

        final ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule simpleModule = new SimpleModule();
        objectMapper.registerModule(simpleModule);
        final String jsonEvent = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(person);
        System.out.println(jsonEvent);
    }
}

以下我尝试过的事情:

  1. 我尝试在Map 上添加@JsonValue,但这会删除我的所有其他值(姓名、年龄、isA 等)
  2. 我尝试了@JsonAnyGetter,它适用于MapString,但不适用于我想要的ArrayList。作为我要求的一部分,我在我的应用程序中以不同的方式处理 ArrayList 位。

有没有办法让它与@JsonSerialize@JsonAnyGetter 一起使用,因为我无法同时使用它们。

有人可以帮忙解决这个问题吗?请指导我找到适当的文档或解决方法,非常感谢。

【问题讨论】:

    标签: java json jackson jackson-databind jackson2


    【解决方案1】:

    wiki page 看来,@JsonUnwrapped 注释应该可以满足您的需求。

    @JsonUnwrapped:用于定义该值的属性注释在序列化时应“解包”(反序列化时再次包装),与 POJO 结构相比,导致数据结构扁平化。

    该类的Javadoc 也有一个看起来合适的示例。

    【讨论】:

    • 非常感谢您的快速响应和示例。我尝试了更多的东西并使用@XmlAnyGetter@JsonSearlize 让它工作。
    • 我会接受这个答案,因为您很快并提供了一些有用的文档和示例。但是,我也会发布我的答案,以便将来对某人有所帮助。再次感谢您的回复。祝你有美好的一天:)
    【解决方案2】:

    正如另一个答案中提到的 @JsonUnwrapped 可能有效,但我使用以下方法使其工作。在这里发帖,因为它可能对将来的某人有所帮助:

    我在MapGetter 方法上添加了@JsonAnyGetter@JsonSearlize 并让它工作。

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, visible = true, property = "isA")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonIgnoreProperties(ignoreUnknown = true)
    @Getter
    @Setter
    @NoArgsConstructor
    @ToString
    class Human {
        private String isA;
        private String name;
        private String age;
    
        @JsonIgnore
        private Map<String, Object> others = new HashMap<>();
    
        @JsonAnyGetter
        @JsonSerialize(using = MyCustomSearlize.class)
        public Map<String,Object> getOther(){
            return others;
        }
    }
    

    MyCustomSearlize 类代码中,我删除了开始和结束对象

        @Override
        public void serialize(Map<String, Object> value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            recusiveSerializer(value, gen, serializers);
        }
    

    【讨论】:

      猜你喜欢
      • 2023-04-07
      • 1970-01-01
      • 2020-11-30
      • 1970-01-01
      • 2015-04-07
      • 2017-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多