我们之前使用的框架(云端点)自动将java.lang.Long序列化为JSON字符串(同时将整数和双精度数保留为JSON数字)。我们正在迁移以使用更标准的Jackson序列化框架。
为了向后兼容,我们需要Jackson能够将Long序列化为String,同时将整数和Double默认保留为JSON数字。我在杰克逊身上看不到任何这样做的功能。这个是可能的吗?
发布于 2017-11-04 06:08:22
为Long.class和long.class使用自定义序列化程序
public static class LongSerializer extends JsonSerializer<Long> {
@Override
public void serialize(Long value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(value.toString());
}
}
public static class LongDeserializer extends JsonDeserializer<Long> {
@Override
public Long deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
return p.getValueAsLong();
}
}您需要向您的映射器注册它们:
public static void main(String[] args) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(long.class, new LongSerializer());
module.addSerializer(Long.class, new LongSerializer());
module.addDeserializer(long.class, new LongDeserializer());
module.addDeserializer(Long.class, new LongDeserializer());
objectMapper.registerModule(module);
Test test = new Test();
String json = objectMapper.writeValueAsString(test);
System.out.println(json);
}发布于 2017-11-04 19:48:45
选项1.定制序列化程序
@teppic答案应该适用于大多数情况,但是
com.fasterxml.jackson.databind.ser.std.ToStringSerializer serializermodule.addSerializer(Long.class,ToStringSerializer.instance);module.addSerializer(long.class,Long.class);因为自定义序列化程序方法实际上不能处理另一个自定义序列化程序使用this JsonGenerator method时的情况(JsonGenerator) g.writeNumber((Long)值);
这里最重要的边缘情况是long[].class
静态类MyBean { long val = 1;//运行正常"1“Long val2 = 2L;//运行正常"2”long[] = { 1,2 };//不工作1,2 }
所以你实际上可以
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(Long.class, ToStringSerializer.instance);
module.addSerializer(long.class, ToStringSerializer.instance);
module.addSerializer(long[].class, new JsonSerializer<long[]>(){
@Override
public final void serialize(
long[] value, JsonGenerator g, SerializerProvider provider)
throws IOException {
g.writeStartArray();
for (int i = 0, len = value.length; i < len; ++i)
g.writeString(String.valueOf(value[i]));
g.writeEndArray();
}
});
// register every other serializers that use
// (JsonGenerator) g.writeNumber((long)value);
// like AtomicLong, if you use it in your code
mapper.registerModule(module);
MyBean bean = new MyBean();
String json = mapper.writeValueAsString(bean);
MyBean myBean2 = mapper.readValue(json, MyBean.class);
System.out.println(json);
System.out.println(myBean2);
System.out.println(mapper.writeValueAsString(myBean2));
}选项2.自定义JsonFactory和JsonGenerator
但话又说回来,这对你来说足够了吗?你确定没有人会尝试使用jsonGenerator.writeNumber(long)吗?或者你有其他的类,实际上是默认使用它的吗?因此,100%可行的解决方案是在ObjectMapper上注册自定义JsonFactory,并使用2个被覆盖的方法_createGenerator和_createUTF8Generator
JsonFactory factory = new JsonFactory(){
@Override
protected JsonGenerator _createGenerator(Writer out, IOContext ctxt)
throws IOException {
WriterBasedJsonGenerator gen = new WriterBasedJsonGenerator(ctxt,
_generatorFeatures, _objectCodec, out){
@Override
public void writeNumber(long l) throws IOException {
writeString(String.valueOf(l));
}
};
return _internalSuperSetup(gen);
}
@Override
protected JsonGenerator _createUTF8Generator(OutputStream out, IOContext ctxt)
throws IOException {
UTF8JsonGenerator gen = new UTF8JsonGenerator(ctxt,
_generatorFeatures, _objectCodec, out){
@Override
public void writeNumber(long l) throws IOException {
writeString(String.valueOf(l));
}
};
return _internalSuperSetup(gen);
}
// reuse code from _createUTF8Generator and _createGenerator super methods
private JsonGenerator _internalSuperSetup(JsonGenerator gen){
if (_characterEscapes != null) gen.setCharacterEscapes(_characterEscapes);
SerializableString rootSep = _rootValueSeparator;
if (rootSep != DefaultPrettyPrinter.DEFAULT_ROOT_VALUE_SEPARATOR)
gen.setRootValueSeparator(rootSep);
return gen;
}
};
ObjectMapper mapper = new ObjectMapper(factory);https://stackoverflow.com/questions/47104817
复制相似问题