Java 中的 Jackson JSON 序列化 - 将 k/v 对写入根而不是嵌套在 属性 名称中

Jackson JSON serialization in Java - write k/v pairs to root instead of nested in property name

我需要编写一个遵循以下基本格式的 JSON 字符串:

{ 
    "xmlns": {
       "nskey1" : "nsurl1",
       "nskey2" : "nsurl2"
    },

    "datakey1": "datavalue1",
    "datakey2": "datavalue2"
}

我正在使用以下 class 来呈现数据,并且此 class 的一个实例是使用 Jackson ObjectMapper 序列化的。

public class PayloadData {
    public Map<String, String> payloadData = new TreeMap<String, String>();

    @JsonProperty("xmlns")
    public Map<NamespaceEnum, String> namespaces = new TreeMap<NamespaceEnum, String>();

    @JsonAnyGetter
    public Map<String, String> getPayloadData() {
        return payloadData;
    }
}

如果我按原样序列化这个 class 的实例,结果 JSON 将是这样的:

{ 
    "xmlns": {
       "nskey1" : "nsurl1",
       "nskey2" : "nsurl2"
    },
    "payloadData": {
        "datakey1": "datavalue1",
        "datakey2": "datavalue2"
    },

    "datakey1": "datavalue1",
    "datakey2": "datavalue2"
}

根据命名约定,这是有道理的,但我正在寻找一种方法,将 payloadData 映射放置在 JSON 的根上下文中,而不包含包含 属性 的副本标识符和嵌​​套。我尝试了 很多 各种形式的注释;我试过禁用 ObjectMapper wrap_root_value SerializationFeature;老实说,我觉得我几乎什么都试过了。因此,在我将计算机扔出 window 之前,我需要第二组(甚至更多)眼睛来帮助指出必须非常明显的东西。

在此先感谢您的关注和建议。

编辑:更新了我现在看到的实际输出JSON。数据正在复制,我想删除具有嵌套 属性.

的副本

您可以将 json 数据解析为 HashMap 而不是 class 对象:

public HashMap<String, Object> testJackson(String data) throws IOException {        
    JsonFactory factory = new JsonFactory(); 
    ObjectMapper mapper = new ObjectMapper(factory); 
    TypeReference<HashMap<String,Object>> typeRef 
            = new TypeReference<HashMap<String,Object>>() {};

    HashMap<String,Object> o = mapper.readValue(data, typeRef); 
    return o
}  

HashMap 获取 JSON 数据:

public String getJsonFromMap(HashMap<String, Object> data) {
    return new ObjectMapper().writeValueAsString(data);
}

问题是您为 PayloadData 公开了 2 个访问器:public 属性 和 getter,因此它被序列化了两次。如果可能的话,我建议将您的数据 class 重组为不可变的。例如:

public class PayloadData {
    private final Map<String, String> payloadData;
    private final Map<NamespaceEnum, String> namespaces;

    @JsonCreator
    public PayloadData(@JsonProperty("xmlns") Map<NamespaceEnum, String> namespaces,
                       @JsonProperty("payloadData") Map<String, String> payloadData) {
        this.namespaces = namespaces;
        this.payloadData = payloadData;
    }

    @JsonAnyGetter
    public Map<String, String> getPayloadData() {
        return payloadData;
    }

    @JsonProperty("xmlns")
    public Map<NamespaceEnum, String> getNamespaces() {
        return namespaces;
    }
}

这将为您提供所需的输出,而无需对 ObjectMapper 进行任何配置。