jackson – json编码双精度控制精度

我正在使用double值数组编码复杂的Map结构。 高精度并不重要,输出大小也是如此,所以我试图使用提供的DecimalFormat来获取JSON工具(在本例中为Jackson)来序列化double值。

以下是我最好的镜头,但由于对象映射器没有选择序列化程序来编码数组,因此失败了:

class MyTest { public class MyDoubleSerializer extends JsonSerializer { public void serialize(double[] value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { for (double d : value) { jgen.writeStartArray(); jgen.writeRaw( df.format( d ) ); jgen.writeEndArray(); } } } @Test public void test1() throws Exception { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule("MyModule", new Version(0, 1, 0, "alpha")); module.addSerializer(double[].class, new MyDoubleSerializer()); mapper.registerModule(module); Map data = new HashMap(); double[] doubleList = { 1.1111111111D, (double) (System.currentTimeMillis()) }; data.put( "test", doubleList ); System.out.print( mapper.writeValueAsString( data )); } } 

输出是:

{ “测试”:[1.1111111111,1.315143204964E12}

我在找什么:

{“test”:[1.32E12,1.11E0]}

有任何想法吗?

另外,我不喜欢生成一个String并且写入是原始的 – 我可以将StringBuffer输入到DecimalFormat中吗?

谢谢

通过借用Double的内置序列化程序来管理解决这个问题。

这有点像黑客,因为writeRaw()不关心上下文并且不在数组成员之间编写逗号,所以我正在构建Json编写器并调用它的writeValue()方法来处理它。

奇怪的是,这不适用于问题中的示例(再次没有被称为序列化这些双打),但确实对我的现实世界对象起作用更复杂。

请享用…

 public class JacksonDoubleArrayTest { private DecimalFormat df = new DecimalFormat( "0.##E0" ); public class MyDoubleSerializer extends org.codehaus.jackson.map.ser.ScalarSerializerBase { protected MyDoubleSerializer() { super( Double.class ); } @Override public final void serializeWithType( Double value, JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer ) throws IOException, JsonGenerationException { serialize( value, jgen, provider ); } @Override public void serialize( Double value, JsonGenerator jgen, SerializerProvider provider ) throws IOException, JsonGenerationException { if ( Double.isNaN( value ) || Double.isInfinite( value ) ) { jgen.writeNumber( 0 ); // For lack of a better alternative in JSON return; } String x = df.format( value ); if ( x.endsWith( "E0" ) ) { x = x.substring( 0, x.length() - 2 ); } else if ( x.endsWith( "E1" ) && x.length() == 6 ) { x = "" + x.charAt( 0 ) + x.charAt( 2 ) + '.' + x.charAt( 3 ); } JsonWriteContext ctx = (JsonWriteContext)jgen.getOutputContext(); ctx.writeValue(); if ( jgen.getOutputContext().getCurrentIndex() > 0 ) { x = "," + x; } jgen.writeRaw( x ); } @Override public JsonNode getSchema( SerializerProvider provider, Type typeHint ) { return createSchemaNode( "number", true ); } } @SuppressWarnings("unchecked") private static Map load() throws JsonParseException, JsonMappingException, IOException { ObjectMapper loader = new ObjectMapper(); return (Map)loader.readValue( new File( "x.json" ), Map.class ); } @Test public void test1() throws JsonGenerationException, JsonMappingException, IOException { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule( "StatsModule", new Version( 0, 1, 0, "alpha" ) ); module.addSerializer( Double.class, new MyDoubleSerializer() ); mapper.registerModule( module ); String out = mapper.writeValueAsString( load() ); // System.out.println( out.length() ); } }