【问题标题】:jackson serializer - accessing private properties杰克逊序列化程序 - 访问私有属性
【发布时间】:2020-04-16 01:50:05
【问题描述】:

我有一个 Spring Boot 2 应用程序,其中包含私有属性和公共 getter/setter 模型。杰克逊是2.10.0 版本。

我需要一个自定义序列化器来输出 JSON 而无需扩展一些引用。根据我的阅读,如果该属性是私有的,Jackson 将无法访问它,并且会出现编译错误。除非它应该工作时有公共吸气剂。但事实并非如此。

但如果我将模型中的属性设置为公开,则不会出错。

同样,如果我在序列化器中使用 getter 而不是属性,那么一切都很好。

我看错了,序列化器真的将私有视为私有吗?

@JsonSerialize(using = ClimateSerializer.class)
public class Climate {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "climate_gen")
    private long id;

    private float temperature;
    private float humidity;

    .... getters and setters
}

序列化器

public class ClimateSerializer extends StdSerializer<Climate> {

    public ClimateSerializer() {
        this(null);
    }

    public ClimateSerializer(Class<Climate> t) {
        super(t);
    }

    @Override
    public void serialize(
      final Climate value, final JsonGenerator jgen, final SerializerProvider provider) 
      throws IOException, JsonProcessingException {

        jgen.writeStartObject();
        jgen.writeNumberField("id", value.getId());
        jgen.writeNumberField("temperature", value.getTemperature());
        jgen.writeNumberField("humidity", value.getHumidity());
        jgen.writeEndObject();
    }
}

这会编译。

如果 write*Field 调用被替换为

jgen.writeNumberField("id", value.id);
etc
etc

然后我得到一个编译错误。无法访问私有财产。这与我所读到的背道而驰。如果有公共 getter,Jackson 可以访问私有属性。

显然直接使用 getter 是可以的。有用。但我想知道我读过的各种文档是否有误。

【问题讨论】:

  • 您可以将MCVE 添加到您的问题中,以帮助您更好地理解和回答。

标签: java json spring-boot serialization jackson


【解决方案1】:

如果你想实现自定义序列化器并且不同时公开属性,你可以直接在Climate类中实现com.fasterxml.jackson.databind.JsonSerializable接口:

class Climate implements JsonSerializable {

    private long id;

    private float temperature;
    private float humidity;

    @Override
    public void serialize(JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeStartObject();
        gen.writeNumberField("id", id);
        gen.writeNumberField("temperature", temperature);
        gen.writeNumberField("humidity", humidity);
        gen.writeEndObject();
    }

    @Override
    public void serializeWithType(JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) {
    }
}

您的问题与Jackson 没有直接关系。而是access modifiers。当您想使用默认序列化时,Jackson 使用包装在许多功能中的reflection 将给定的POJO 类序列化为JSON。因此,Jackson 确实可以使用私有字段,但在您的情况下,您希望实现自定义序列化程序,并且您需要自己使用反射来使其工作。在其他情况下,您可以使用default 访问修饰符并将自定义序列化程序ClimateSerializer 和类Climate 放在同一个包中以使其工作。

【讨论】:

  • 最简单的方法是保持属性私有并直接使用公共 getter。当然,每个博客和教程都说使用公共 getter 可以直接在自定义序列化程序中访问私有属性,但我必须设置一些东西来阻止它。
猜你喜欢
  • 1970-01-01
  • 2016-08-24
  • 2017-12-09
  • 1970-01-01
  • 1970-01-01
  • 2020-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多