【问题标题】:Jackson property order based on field value基于字段值的杰克逊属性顺序
【发布时间】:2019-03-12 02:08:34
【问题描述】:

我正在尝试使用Jackson 序列化和反序列化Java 类,而JsonPropertyOrder 取决于类中version 字段的值。如果version = 1,我希望订单是{"start1", "start2"},如果version = 2,订单应该是{"end1", "end2"}
我有以下课程:

 @Builder
 @Value
 @AllArgsConstructor(onConstructor=@__(@JsonCreator))
 @JsonPropertyOrder(custom property order depending on version field)
 public class ClassA {

   @NonNull Integer version;

   @NonNull String start1;

   @NonNull String start2;

   @NonNull String end1;

   @NonNull String end2;
}

如何在运行时根据版本定义JsonPropertyOrder。如果我应该使用自定义Deserializer,我无法弄清楚它应该如何实现并使用ObjectMapper 进行设置。

这是反序列化的代码:

private final ObjectMapper objectMapper = new ObjectMapper();//have initialzed this as a bean
String jsonStr = "{\"version\":1, \"startLat\":\"47.6812\", \"startLng\":\"-122.3268\", \"endLat\":\"47.6074\", \"endLng\":\"-122.3377\"}";
ClassA objA = null;
    try {
        objA = objectMapper.readValue(jsonStr, ClassA.class);
    } catch (IOException e) {
        log.error("Error deserializing the string", jsonStr, e);
    }
return objA;

**编辑:我错过了一个小鬼部分。这里的属性顺序很重要,因为序列化的字符串可能没有字段名称。那有可能吗? 所以 str [1, "47.6812", "-122.3268"] 需要反序列化为字段版本,start1start2

【问题讨论】:

  • json订单有什么影响?
  • 我现在有一个使用特定 json 顺序的版本,将来我需要支持另一个具有不同顺序的版本。因此,根据版本的不同,顺序会发生变化。
  • 是的,但是 json 顺序在消费时仍然无关紧要,请交叉检查一次
  • 我想我的意思是同样的顺序也适用于序列化。因此在版本 1 中,使用特定顺序进行序列化,然后在反序列化期间,根据版本,它应该正确映射字段。基本上取决于版本,我想为 ser/deserialization 设置@JsonPropertyOrder
  • 因此,您有三种可能的JSON 有效负载:1.{"version":1, "startLat":"47.6812", "startLng":"-122.3268", "endLat":"47.6074", "endLng":"-122.3377"}、2.{"version":1, "startLat":"47.6812", "startLng":"-122.3268"} 和3.{"version":2, "endLat":"47.6074", "endLng":"-122.3377"}。你能确认一下吗?这不是有效的JSON{1, "47.6812", "-122.3268"},但这是[1, "47.6812", "-122.3268"]。对象总是必须有属性。另一方的数组可以存储没有属性名称的对象和原语。那么,您需要支持所有 4 种有效载荷还是只支持最后一种?

标签: java jackson json-deserialization jackson-databind


【解决方案1】:

如果这些属性是独占的,为什么不通过删除其中两个来创建更简洁的POJO?您可以通过引入一些isMethod-es 或Enum 来使用12 不同的知识。要将类序列化为JSON array,您需要使用@JsonFormat(shape = JsonFormat.Shape.ARRAY) 注释。要反序列化,您可以使用带有 @JsonCreator@JsonProperty 注释的 3-arg 构造函数。属性是final。所有这些都使得 - 类得到了很好的实施。见例子:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.Objects;

public class JsonApp {

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

        ClassA classA1 = new ClassA(1, "Start_1", "Start_2");
        ClassA classA2 = new ClassA(2, "End_1", "End_2");

        String json1 = mapper.writeValueAsString(classA1);
        String json2 = mapper.writeValueAsString(classA2);

        System.out.println(json1);
        System.out.println(json2);

        System.out.println(mapper.readValue(json1, ClassA.class));
        System.out.println(mapper.readValue(json2, ClassA.class));
    }
}

@JsonFormat(shape = JsonFormat.Shape.ARRAY)
class ClassA {

    private final Integer version;

    private final String value1;
    private final String value2;

    @JsonCreator
    public ClassA(@JsonProperty("version") Integer version,
                  @JsonProperty("start1") String value1,
                  @JsonProperty("start2") String value2) {
        Objects.requireNonNull(version);
        if (!(version == 1 || version == 2)) {
            throw new IllegalArgumentException("Version is not supported!");
        }
        this.version = version;
        this.value1 = value1;
        this.value2 = value2;
    }

    @JsonIgnore
    public boolean isStart() {
        return version == 1;
    }

    @JsonIgnore
    public boolean isEnd() {
        return version == 2;
    }

    public Integer getVersion() {
        return version;
    }

    public String getValue1() {
        return value1;
    }

    public String getValue2() {
        return value2;
    }

    @Override
    public String toString() {
        return "ClassA{" +
                "version=" + version +
                ", value1='" + value1 + '\'' +
                ", value2='" + value2 + '\'' +
                ", isEnd()='" + isEnd() + '\'' +
                ", isStart()='" + isStart() + '\'' +
                '}';
    }
}

上面的代码打印:

[1,"Start_1","Start_2"]
[2,"End_1","End_2"]
ClassA{version=1, value1='Start_1', value2='Start_2', isEnd()='false', isStart()='true'}
ClassA{version=2, value1='End_1', value2='End_2', isEnd()='true', isStart()='false'}

【讨论】:

  • 谢谢@Michal Ziober !!
猜你喜欢
  • 2016-08-24
  • 1970-01-01
  • 1970-01-01
  • 2016-12-14
  • 1970-01-01
  • 2017-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多