杰克逊在反序列化期间设置值

时间:2014-06-12 21:42:20

标签: java json jackson

我有一个像下面这样的对象结构:

public class Product {
    int id;
    String name;
    Size[] sizes;
    boolean organic;
}

public class Size {
    int id;
    String value;
    @JsonIgnore String info;
}

在解析Product类的JSON时,我想将每个大小的信息设置为String "Organic"。在organic属性的setter中,我检查值并迭代大小,为每个大小设置信息。

@JsonProperty("organic")
public void setOrganic(boolean organic) {
    this.organic = organic;
    if (organic) 
        for(Size size : sizes) size.info = "Organic";
}

首先,这种方法似乎很脆弱,因为它取决于JSON中属性的顺序,其次,它似乎并不总是有效。对于JSON具有更多属性的生产环境,我似乎能够在子对象(Size这里)上设置属性,并在解析期间读取和记录它们,但是当我从最终读取它时反序列化对象,这些值始终为null。同样,对于我设置为测试的较小测试用例,这种行为似乎有所不同。

有谁知道更好的方法吗?

1 个答案:

答案 0 :(得分:1)

执行此操作的适当位置将在这些类之外以及此类业务逻辑更合适的位置。

您可以创建一个Builder类,允许您设置结果对象的所有属性,并在调用构造最终对象的build()方法时,根据需要设置任何其他值。然后,您可以将Jackson注释应用于Builder类,并对其应用任何验证,而不是它创建的类。这样,您可以保证产品的任何实例都是完整且有效的。

如果您采用我的原始建议并将逻辑移动到应用程序的业务层,那么您只需将构建器传递给适当的方法,检查Product.Builder上的organic值,然后迭代Size。构建器列表并适当更改其信息值。

使用构建器来保存逻辑可能看起来像这样(你正在寻找的逻辑一直在底部):

public class Size {
    private final int id;
    private final String value;
    private final String info;

    public Size(int id, String value, String info) {
        this.id = id;
        this.value = value;
        this.info = info;
    }

    public int getId() {
        return id;
    }

    public String getValue() {
        return value;
    }

    public String getInfo() {
        return info;
    }

    public static class Builder {
        private int id;
        private String value;
        private String info;

        public Builder setId(int id) {
            this.id = id;
            return this;
        }

        public Builder setValue(String value) {
            this.value = value;
            return this;
        }

        @JsonIgnore
        public Builder setInfo(String info) {
            this.info = info;
            return this;
        }

        public Size build() {
            return new Size(id, value, info);
        }
    }
}

public class Product {
    private final int id;
    private final String name;
    private final Size[] sizes;
    private final boolean organic;

    public Product(int id, String name, Size[] sizes, boolean organic) {
        this.id = id;
        this.name = name;
        this.sizes = sizes;
        this.organic = organic;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public Size[] getSizes() {
        return sizes;
    }

    public boolean isOrganic() {
        return organic;
    }

    public static class Builder {
        private int id;
        private String name;
        private List<Size.Builder> sizeBuilders;
        private boolean organic;

        public Builder setId(int id) {
            this.id = id;
            return this;
        }

        public Builder setName(String name) {
            this.name = name;
            return this;
        }

        public Builder setSizeBuilders(List<Size.Builder> sizeBuilders) {
            this.sizeBuilders = sizeBuilders;
            return this;
        }

        public Builder setOrganic(boolean organic) {
            this.organic = organic;
            return this;
        }

        public Product build() {
            if (organic) {
                for (Size.Builder sizeBuilder : sizeBuilders) {
                    sizeBuilder.setInfo("Organic");
                }
            }
            Size[] sizes = new Size[sizeBuilders.size()];
            for (int i = 0; i < sizeBuilders.size(); i++) {
                sizes[i] = sizeBuilders.get(i).build();
            }
            return new Product(id, name, sizes, organic);
        }
    }
}