如何为 Json 对象使用动态属性名称

Posted

技术标签:

【中文标题】如何为 Json 对象使用动态属性名称【英文标题】:How to use dynamic property names for a Json object 【发布时间】:2019-09-05 04:08:20 【问题描述】:

我们如何使 JSON 属性名称动态化。例如

public class Value 
    @JsonProperty(value = "value")
    private String val;

    public void setVal(String val) 
        this.val = val;
    

    public String getVal() 
        return val;
    

当序列化这个对象时,它被保存为"value": "actual_value_saved",但我想让密钥也像"new_key": "actual_value_saved" 一样动态。非常感谢任何帮助。

【问题讨论】:

Jackson dynamic property names的可能重复 您想只用"new_key" 保存它,还是想有时用"new_key" 保存它,有时用"value" 保存它?如果是,基于什么理由? @Bentaye 是的,基于名称可能会更改的要求。可以是"value""new_key""any_random_string" @Prasad 您从哪里获得所需的字段名称?你能在你的 Value 对象中计算它吗? @Bentaye 我已经通过使用自定义JsonSerializerJsonTypeInfo 的解决方案允许我们修改值但不能修改键。我的要求是有一个动态密钥。我想使用这个 POJO 作为一个公共对象来打印类似 "name": "user" "phone": "1234567890" 的东西。 【参考方案1】:

你可以使用JsonAnySetterJsonAnyGetter注解。后面可以使用Map 实例。如果您始终使用one-key-object,则可以使用Collections.singletonMap,在其他情况下使用HashMap 或其他实现。下面的示例显示了您可以轻松地使用这种方法并根据需要创建任意数量的随机key-s:

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;

public class JsonApp 

    public static void main(String[] args) throws Exception 
        DynamicJsonsFactory factory = new DynamicJsonsFactory();
        ObjectMapper mapper = new ObjectMapper();

        System.out.println(mapper.writeValueAsString(factory.createUser("Vika")));
        System.out.println(mapper.writeValueAsString(factory.createPhone("123-456-78-9")));
        System.out.println(mapper.writeValueAsString(factory.any("val", "VAL!")));
    


class Value 

    private Map<String, String> values;

    @JsonAnySetter
    public void put(String key, String value) 
        values = Collections.singletonMap(key, value);
    

    @JsonAnyGetter
    public Map<String, String> getValues() 
        return values;
    

    @Override
    public String toString() 
        return values.toString();
    


class DynamicJsonsFactory 

    public Value createUser(String name) 
        return any("name", name);
    

    public Value createPhone(String number) 
        return any("phone", number);
    

    public Value any(String key, String value) 
        Value v = new Value();
        v.put(Objects.requireNonNull(key), Objects.requireNonNull(value));

        return v;
    

上面的代码打印:

"name":"Vika"
"phone":"123-456-78-9"
"val":"VAL!"

【讨论】:

【参考方案2】:

您可以将所有可能的名称作为变量,并对它们进行注释,以便它们在为空时被忽略。这样,您只能在 JSON 中获取具有值的那个

然后更改您的设置器以输入映射到您想要的键的变量。

class Value 

    @JsonProperty("val")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private String val;

    @JsonProperty("new_key")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private String newKey;

    @JsonProperty("any_random_string")
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private String anyRandomString;

    public void setVal(String s) 
        if(/* condition1 */)
            this.val = s;
        else if (/* condition2 */) 
            this.newKey = s;
         else  if (/* condition3 */) 
            this.anyRandomString = s;
        
    


【讨论】:

虽然想法很聪明,但每次读取的字段数并不相同。它们往往会及时更改,因此在这种方法中,我可能需要在每次字段更改时更新代码。【参考方案3】:

好问题@Prasad,这个答案与 JAVA 或 SPRING BOOT 无关,我只是提出这个答案,因为我搜索过使用 node 来做到这一点,并希望这能以某种方式帮助某人。在 javascript 中,我们可以为 JSON 对象添加动态属性名称,如下所示

var dogs = ;

var dogName = 'rocky';

dogs[dogName] = 
    age: 2,
    otherSomething: 'something'
;

dogName = 'lexy';

dogs[dogName] = 
    age: 3,
    otherSomething: 'something'
;

console.log(dogs);

但是当我们需要动态改名字的时候就不得不

    获取该属性 并创建另一个具有相同内容和新名称的属性 并从 JSON 中删除旧属性 将新属性分配给 JSON

除此方法外,还有另一种动态更改 JSON 名称的方法,在此先感谢

【讨论】:

以上是关于如何为 Json 对象使用动态属性名称的主要内容,如果未能解决你的问题,请参考以下文章

Json 使用动态属性名称反序列化对象数组

XML De/Serialization:如何为类的不同实例的相同属性定义不同的名称

如何使用动态名称实现属性()(在python中)

如何使用jackson映射动态json属性名称以进行spring rest模板请求

如何为动态生成的输入文件添加“多个”属性?

将 JSON 反序列化为 C# 类,其中 JSON 中的属性名称是动态的