java 杰克逊反序列化绕过最终领域
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30340946/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hymanson deserialization circumventing final fields
提问by surasak
Here's the code
这是代码
import com.fasterxml.Hymanson.annotation.JsonProperty;
import com.fasterxml.Hymanson.databind.ObjectMapper;
import lombok.Data;
import lombok.ToString;
public class Main {
public static void main(String[] args) throws Exception {
Fields f1 = new Fields(1);
System.out.println(f1);
ObjectMapper mapper = new ObjectMapper();
String str = mapper.writeValueAsString(f1);
System.out.println(str);
Fields f2 = mapper.readValue(str, Fields.class);
System.out.println(f2);
}
@Data
@ToString
public static class Fields {
private final long value1;
private final long value2;
public Fields(@JsonProperty("blah") long value) {
this.value1 = value++;
this.value2 = value++;
System.out.println(this);
}
}
}
Output
输出
Main.Fields(value1=1, value2=2)
Main.Fields(value1=1, value2=2)
{"value1":1,"value2":2}
Main.Fields(value1=0, value2=1)
Main.Fields(value1=1, value2=2)
My questions are:
我的问题是:
- Why did Hymanson modify private final fields that do not have setters after finish constructing it? If this is intended, how do I turn it off?
- If Hymanson is able to set fields directly, why is it required that I annotate the constructor with @JsonProperty? (Removing @JsonProperty from Fields results in error; and I didn't even need to annotate with correct properties)
- 为什么Hymanson在构建完成后修改没有setter的私有final字段?如果这是有意的,我该如何关闭它?
- 如果 Hymanson 能够直接设置字段,为什么需要我用 @JsonProperty 注释构造函数?(从字段中删除 @JsonProperty 会导致错误;我什至不需要使用正确的属性进行注释)
Thank you
谢谢
回答by Sotirios Delimanolis
Why is it required that I annotate the constructor with @JsonProperty?
为什么需要我用@JsonProperty 注释构造函数?
It's not. What is required is an accessible constructor. You can either have a parameterless constructor
不是。需要的是一个可访问的构造函数。你可以有一个无参数的构造函数
public Fields() {
this.value1 = 0;
this.value2 = 0;
System.out.println("cons: " + this);
}
(that necessarily initializes the fields since they are final
) or you can have a constructor that Hymanson will try to resolve based on the declared @JsonProperty
name. Note that JsonProperty#required
is false
by default.
(必须初始化字段,因为它们是final
)或者您可以拥有一个构造函数,Hymanson 将尝试根据声明的@JsonProperty
名称解析该构造函数。请注意,这JsonProperty#required
是false
默认设置。
Why did Hymanson modify private final fields that do not have setters after finish constructing it? If this is intended, how do I turn it off?
为什么Hymanson在构建完成后修改没有setter的私有final字段?如果这是有意的,我该如何关闭它?
Because it can. It thus allows you to use immutable types with deserialization. There is no built-in way that I know of through which you can disable this feature.
因为可以。因此,它允许您将不可变类型与反序列化一起使用。据我所知,没有内置的方法可以禁用此功能。
回答by Oleksandr Matiash
Why did Hymanson modify private final fields that do not have setters after finish constructing it? If this is intended, how do I turn it off?
为什么Hymanson在构建完成后修改没有setter的私有final字段?如果这是有意的,我该如何关闭它?
You can set MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS
property to false
(it is true
by default) when configuring your mapper.
您可以在配置映射器时将MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS
属性设置为false
(true
默认情况下)。
Example:
例子:
import com.fasterxml.Hymanson.annotation.JsonCreator;
import com.fasterxml.Hymanson.annotation.JsonProperty;
import com.fasterxml.Hymanson.databind.DeserializationFeature;
import com.fasterxml.Hymanson.databind.MapperFeature;
import com.fasterxml.Hymanson.databind.ObjectMapper;
public class Temp {
private static final String RAW = "{\"value1\": \"aabbcc\",\"value2\":\"zzzzz\"}";
public static void main(String[] args) throws Exception {
System.out.println(new ObjectMapper().readValue(RAW, TestClass.class));
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // you will receive UnrecognizedPropertyException without this line
mapper.configure(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS, false);
System.out.println(mapper.readValue(RAW, TestClass.class));
}
public static class TestClass {
private final String value1;
private final String value2;
@JsonCreator
public static TestClass createTestClass(
@JsonProperty("value1") String value1,
@JsonProperty("blah") String value2) {
return new TestClass(value1, value2);
}
private TestClass(String value1, String value2) {
this.value1 = value1;
this.value2 = value2;
}
public String getValue1() {
return value1;
}
public String getValue2() {
return value2;
}
@Override
public String toString() {
return "TestClass{" + "value1=" + value1 + ", value2=" + value2 + '}';
}
}
}
}
Output:
输出:
TestClass{value1=aabbcc, value2=zzzzz}
TestClass{value1=aabbcc, value2=null}