2012-07-19 61 views
6

我正面临以下问题。当杰克逊串行传递包裹的原语序列,该原语序列化为是,例如:使用Jackson序列化根原始对象

objectMapper = new ObjectMapper(); 

StringWriter w = new StringWriter(); 
objectMapper.writeValue(w, Integer.valueOf(10)); 
System.out.println(w.toString()); 

产生10作为输出。但10不是有效的JSON(根据jsonlint),应该用方括号([10],因此它将是一个单元素数组)或花括号({value:10},因此它将是一个具有伪属性的对象) 。问题影响数字,java.lang.Stringjava.util.Date,...

我的问题是:如何让杰克逊执行包装?杰克逊不应该总是产生有效的JSON吗?

我已经分析了杰克逊的行为,并启用SerializationConfig.Feature.WRAP_ROOT_VALUE:它没有像我期望的那样工作。原语现在被序列化为有效的JSON({"Integer":10}),但“常规”Java bean也被打包,这是不受欢迎的({"MyBean":{"field":value, ...}}而不是{"field":value, ...})。

如果有人可以建议如何定制杰克逊,也许使用自定义序列化程序。困难在于,有必要从根本原始属性(不需要被包装)区分根原始包装(需要被包装)。

为了使故事完整:Jackson的串行器被用作Spring MVC的消息转换器,我怀疑编写钩子来截取原语的序列化是相当容易的(它不会调用Jackson,但在必要时会简单地返回"[" + String.toString(obj) + "]" )。所以我宁愿与调谐杰克逊解决方案。

+0

我建议在https://github.com/FasterXML/jackson-databind/issues登录增强请求 – 2012-07-20 16:26:39

回答

3

最后的自定义序列

import java.io.IOException; 

import org.codehaus.jackson.JsonGenerationException; 
import org.codehaus.jackson.JsonGenerator; 
import org.codehaus.jackson.map.SerializerProvider; 
import org.codehaus.jackson.map.ser.std.ScalarSerializerBase; 

public class NumberSerializer extends ScalarSerializerBase<Number> { 

    protected NumberSerializer() { 
     super(Number.class); 
    } 

    @Override 
    public void serialize(Number value, JsonGenerator jgen, SerializerProvider provider) throws IOException, 
       JsonGenerationException { 
     if (jgen.getOutputContext().inRoot()) { 
      jgen.writeStartArray(); 
      jgen.writeNumber(value.longValue()); 
      jgen.writeEndArray(); 
     } 
     else { 
      jgen.writeNumber(value.longValue()); 
     } 
    } 
} 

没有工作给我。串行器可以注册为模块(参见here)。

使用此seriazlier时的注意事项:因为它将所有原始图转换为只有一个元素的原始数组,因此在某种意义上打破了反射原理A != desrialize(serialize(A))其中A是一些原始图元。

相关问题