【问题标题】:Update the JSON element to NULL if it has a specific value in it如果 JSON 元素中有特定值,则将其更新为 NULL
【发布时间】:2019-03-05 07:41:08
【问题描述】:

我有一个 JSON,看起来像,

{
 "person": {
  "name":"Sam", 
  "surname":"ngonma"
 },
 "car": {
  "make":"toyota", 
  "model":"yaris"
 }
}

我正在使用以下几行将其写入 Amazon SQS,

ObjectMapper mObjectMapper = new ObjectMapper();
sqsExtended.sendMessage(new SendMessageRequest(awsSQSUrl, mObjectMapper.writeValueAsString(claim)));

我有一个单独的值数组,如果 JSON 在该数组中有它的值,我必须将该字段写为null

如果我的字符串数组是["Sam", "Toyota"],我的最终 JSON 应该是这样的,

{
 "person": {
  "name":null, 
  "surname":"ngonma"
 },
 "car": {
  "make":null, 
  "model":"yaris"
 }
}

字符串数组已外部化。它将来也可能具有其他价值。有人可以建议我一个很好的链接或想法来解决这个问题吗?

【问题讨论】:

  • 在您开始将其序列化为 JSON 之前,让您的声明对象正确?
  • @Mick,什么是“声明对象”?
  • 您的示例中名为“claim”的对象
  • 您需要为POJO 类编写自定义序列化程序,或者在序列化之前在POJO 上执行此操作。见Ignore Serialize field based on another field value

标签: java json spring-boot jackson


【解决方案1】:

我能想到的最灵活的方法是使用 Jackson 的 JsonAnyGetter 注释。它允许您向 Jackson 提供一个 Map 表示您的 pojo 状态的表示。从Map 过滤值可以以迭代方式完成。从包含Maps 的Map 中过滤值可以递归方式完成。

这是我根据提供的问题构建的解决方案

public class Claim {
    Map<String, Object> properties = new HashMap<>();

    public Claim() {
        // may be populated from instance variables
        Map<String, String> person = new HashMap<>();
        person.put("name", "Sam");
        person.put("surname", "ngonma");
        properties.put("person", person);
        Map<String, String> car = new HashMap<>();
        car.put("make", "Toyota");
        car.put("model", "yaris");
        properties.put("car", car);
    }

    // nullify map values based on provided array
    public void filterProperties (String[] nullifyValues) {
        filterProperties(properties, nullifyValues);
    }

    // nullify map values of provided map based on provided array
    @SuppressWarnings("unchecked")
    private void filterProperties (Map<String, Object> properties, String[] nullifyValues) {
        // iterate all String-typed values
        // if value found in array arg, nullify it
        // (we iterate on keys so that we can put a new value)
        properties.keySet().stream()
            .filter(key -> properties.get(key) instanceof String)
            .filter(key -> Arrays.asList(nullifyValues).contains(properties.get(key)))
            .forEach(key -> properties.put(key, null));
        // iterate all Map-typed values
        // call this method on value
        properties.values().stream()
            .filter(value -> value instanceof Map)
            .forEach(value -> filterProperties((Map<String, Object>)value, nullifyValues));
    }

    // provide jackson with Map of all properties
    @JsonAnyGetter
    public Map<String, Object> getProperties() {
        return properties;
    }
}

测试方法

public static void main(String[] args) {
    try {
        ObjectMapper mapper = new ObjectMapper();
        Claim claim = new Claim();
        claim.filterProperties(new String[]{"Sam", "Toyota"});
        System.out.println(mapper.writeValueAsString(claim));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

输出

{"car":{"model":"yaris","make":null},"person":{"surname":"ngonma","name":null}}

【讨论】:

猜你喜欢
  • 2014-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-16
  • 1970-01-01
  • 2019-04-21
相关资源
最近更新 更多