Jackson YAML-将null序列化为空值

时间:2018-11-05 23:12:12

标签: jackson

我正在尝试自定义字符串的序列化,以避免YAML文件中的'null'值。

我到目前为止的代码:

YAMLFactory yamlFactory = new YAMLFactory();
ObjectMapper mapper = new ObjectMapper(yamlFactory);
DefaultSerializerProvider sp = new DefaultSerializerProvider.Impl();
sp.setNullValueSerializer(new NullSerializer());
ObjectMapper m = new ObjectMapper();
mapper.setSerializerProvider(sp);

Map<String, Object> data = new HashMap<>();
data.put("aString", "test");
data.put("aNullObject", null);
data.put("anEmptyString", "");

String output = mapper.writeValueAsString(data);
System.out.println(output);

NullSerializer:

public class NullSerializer extends JsonSerializer<Object> {
    public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
            throws IOException, JsonProcessingException {
        jgen.writeString("");
    }
}

结果:

---
aNullObject: ""
aString: "test"
anEmptyString: ""

问题是writeString正在写一个空字符串,而我试图完全拥有一个空值。

所需结果:

---
aNullObject: 
aString: "test"
anEmptyString: ""

我尝试使用jgen.writeRaw("");,但出现此错误:

Caused by: java.lang.UnsupportedOperationException: Operation not supported by generator of type com.fasterxml.jackson.dataformat.yaml.YAMLGenerator
    at com.fasterxml.jackson.core.JsonGenerator._reportUnsupportedOperation(JsonGenerator.java:1967)
    at com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.writeRaw(YAMLGenerator.java:590)
    at com.example.jackson.NullSerializer.serialize(NullSerializer.java:13)
    at com.fasterxml.jackson.databind.SerializerProvider.defaultSerializeNull(SerializerProvider.java:1127)
    at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFields(MapSerializer.java:711)
    ... 7 more

3 个答案:

答案 0 :(得分:1)

对我来说,禁用“ MINIMIZE_QUOTES”功能无效,但仍然写入了一个空字符串。我发现的唯一解决方案是重写ObjectMapper和YamlGenerator并允许YamlGenerator写入空的原始值。而且,您还必须提供一个自定义的null序列化程序,该序列化程序将写入此原始值。

class YamlObjectMapper(yamlFactory: YAMLFactory) : ObjectMapper(yamlFactory) {
init {
    val dS = DefaultSerializerProvider.Impl()
    dS.setNullValueSerializer(NullSerializer)
    setSerializerProvider(dS)
}}

class RawYAMLFactory : YAMLFactory() {

override fun _createGenerator(out: Writer?, ctxt: IOContext?): YAMLGenerator? {
    val feats = _yamlGeneratorFeatures
    return RawYamlGenerator(ctxt, _generatorFeatures, feats, _objectCodec, out, _version)
}}

private object NullSerializer : JsonSerializer<Any?>() {

override fun serialize(value: Any?, jgen: JsonGenerator, provider: SerializerProvider?) {
    jgen.writeRaw("")
}}

private class RawYamlGenerator(ctxt: IOContext?, jsonFeatures: Int, yamlFeatures: Int,
                           codec: ObjectCodec, out: Writer?, version: DumperOptions.Version?)
: YAMLGenerator(ctxt, jsonFeatures, yamlFeatures, codec, out, version) {

override fun writeRaw(c: String) {
    _writeContext.writeValue()
    _emit(_scalarEvent("", DumperOptions.ScalarStyle.PLAIN))
}}

答案 1 :(得分:0)

我有一个类似的问题,但是直接使用一个枚举(或对象)而不是一个字符串,您可以实现一个序列化程序,并决定在序列化信息之前添加或删除“””。

例如

public class Data {
  private String aString;
  private MyData aNullObject;
  private String anEmptyString;
 ...
}

public class MyData {
  private String value;
  ....
}

public class MySerializer {
  @Override
    public void serialize(
            MyData data, JsonGenerator jgen, SerializerProvider provider)
            throws IOException {

        YAMLGenerator yamlGenerator = (YAMLGenerator) jgen;
        //DISABLE QUOTES
        yamlGenerator.enable(YAMLGenerator.Feature.MINIMIZE_QUOTES);
        yamlGenerator.writeString(data.getValue());
        //ENABLE QUOTES AGAIN
        yamlGenerator.disable(YAMLGenerator.Feature.MINIMIZE_QUOTES);
    }

}

ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
SimpleModule module = new SimpleModule();
module.addSerializer(MyData.class, new MySerializer());
mapper.registerModule(module);

我希望能正确解释...

答案 2 :(得分:0)

基于@Yuliia Liubchyk解决方案-我将他的代码重写为Java。

实例:

   var yamlObjectMapper = new YamlObjectMapper(new RawYamlFactory().
                enable(YAMLGenerator.Feature.MINIMIZE_QUOTES)).
                findAndRegisterModules();
   
class NullValueSerializer extends JsonSerializer<Object> {
    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeRaw("");
    }
}
public class RawYamlFactory extends YAMLFactory {
    @Override
    protected YAMLGenerator _createGenerator(Writer out, IOContext ctxt) throws IOException {
        var feats = _yamlGeneratorFeatures;
        return new RawYamlGenerator(ctxt, _generatorFeatures, feats, _objectCodec, out, _version);
    }
}
public class RawYamlGenerator extends YAMLGenerator {

    public RawYamlGenerator(IOContext ctxt, int jsonFeatures, int yamlFeatures,
                            ObjectCodec codec, Writer out, DumperOptions.Version version) throws IOException {
        super(ctxt, jsonFeatures, yamlFeatures, codec, out, version);
    }

    @Override
    public void writeRaw(String text) throws IOException {
        _writeContext.writeValue();
        _emit(_scalarEvent("", DumperOptions.ScalarStyle.PLAIN));
    }
}
public class YamlObjectMapper extends ObjectMapper {

    public YamlObjectMapper(YAMLFactory jf) {
        super(jf);
        final DefaultSerializerProvider.Impl ds = new DefaultSerializerProvider.Impl();
        ds.setNullValueSerializer(new NullValueSerializer());
        setSerializerProvider(ds);
    }

}