简体   繁体   English

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

[英]Jackson Setting Values During Deserialization

I have a object structure like the following: 我有一个如下的对象结构:

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

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

While parsing the JSON for the Product class, I want to set the info for each of the sizes to the String "Organic" . 在解析Product类的JSON时,我想将每种尺寸的信息设置为String "Organic" In the setter for the organic property I check the value and iterate over the sizes, setting the info for each. organic属性的设置器中,我检查值并遍历大小,为每个属性设置信息。

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

First, this approach seems to be brittle as it depends on the order of properties in the JSON and secondly, it doesn't always seem to work. 首先,这种方法似乎很脆弱,因为它取决于JSON中属性的顺序,其次,它似乎并不总是有效。 For a production environment, where JSON has a lot more properties, I seem to be able to set the properties on the sub-object ( Size here) and read and log them during parsing but when I read it from the final deserialized object, those values are always null. 对于JSON具有更多属性的生产环境,我似乎能够在子对象(此处为Size )上设置属性,并在解析过程中读取和记录它们,但是当我从最终反序列化对象中读取它们时,值始终为null。 Again, this behavior seems to be different for the smaller test cases I set up to test. 同样,对于我设置要测试的较小的测试用例,此行为似乎有所不同。

Does anyone know of a better way to do this ? 有谁知道更好的方法吗?

The appropriate place to do this would be outside of these classes and some place where this type of business logic is more appropriate. 进行此操作的适当位置将在这些类之外,并且在某些位置更适合使用这种类型的业务逻辑。

You could create a Builder class that allows you to set all of the properties for the resulting object and when the build() method that constructs the final object is called, set any additional values as appropriate. 您可以创建一个Builder类,该类允许您设置结果对象的所有属性,并在调用构造最终对象的build()方法时,适当地设置任何其他值。 You would apply the Jackson annotations to the Builder class then, and apply any validation to it instead of the class that it creates. 然后,您将Jackson注释应用于Builder类,并对其进行任何验证,而不是对它创建的类进行验证。 This way, you guarantee that any instance of a Product would be complete and valid. 这样,您可以保证任何产品实例都是完整有效的。

If you take my original suggestion and move the logic into a business layer of your application then you would simply pass the Builders to the appropriate method, check the value of organic on the Product.Builder, and then iterate over the Size.Builder list and change their info values appropriately. 如果您采用我的原始建议并将逻辑移至应用程序的业务层,则只需将Builders传递给适当的方法,检查Product.Builder上的Organic的值,然后遍历Size.Builder列表,然后适当更改其信息值。

Using the Builders to hold the logic might look something like this (the logic you're looking for is all the way at the bottom): 使用构建器来保存逻辑可能看起来像这样(您正在寻找的逻辑始终在底部):

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);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM