Java 双精度受控的jackson-json编码
我正在用双值数组编码一个复杂的映射结构。 高精度并不重要,输出大小也不重要,所以我试图让JSON工具(本例中为Jackson)使用提供的DecimalFormat序列化双精度值 以下是我的最佳方案,但这失败了,因为对象映射程序没有选择序列化程序对数组进行编码:Java 双精度受控的jackson-json编码,java,json,serialization,jackson,Java,Json,Serialization,Jackson,我正在用双值数组编码一个复杂的映射结构。 高精度并不重要,输出大小也不重要,所以我试图让JSON工具(本例中为Jackson)使用提供的DecimalFormat序列化双精度值 以下是我的最佳方案,但这失败了,因为对象映射程序没有选择序列化程序对数组进行编码: class MyTest { public class MyDoubleSerializer extends JsonSerializer<double[]> { public void serialize(d
class MyTest
{
public class MyDoubleSerializer extends JsonSerializer<double[]>
{
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<String, Object> data = new HashMap<String, Object>();
double[] doubleList = { 1.1111111111D, (double) (System.currentTimeMillis()) };
data.put( "test", doubleList );
System.out.print( mapper.writeValueAsString( data ));
}
}
classmytest
{
公共类MyDoubleSerializer扩展JsonSerializer
{
public void serialize(双[]值,JsonGenerator jgen,SerializerProvider提供程序)引发IOException,JsonProcessingException
{
for(双d:值)
{
jgen.writestarray();
jgen.writeRaw(df.format(d));
jgen.writeEndArray();
}
}
}
@试验
public void test1()引发异常
{
ObjectMapper mapper=新的ObjectMapper();
SimpleModule=新的SimpleModule(“MyModule”,新版本(0,1,0,“alpha”);
addSerializer(double[].class,新的MyDoubleSerializer());
映射器注册表模块(模块);
映射数据=新的HashMap();
double[]doubleList={1.1111111d,(double)(System.currentTimeMillis())};
数据输入(“测试”,双重列表);
System.out.print(mapper.writeValueAsString(数据));
}
}
输出为:
{“测试”:[1.1111111111,1.315143024964E12}
我想要的是:
{“测试”:[1.32E12,1.11E0]}
有什么想法吗
另外,我不喜欢生成字符串并按原始格式写入—是否可以将StringBuffer输入到DecimalFormat中来实现这一点
感谢通过借用内置的双精度序列化程序,成功地解决了这个问题 这有点像黑客,因为writeRaw()不关心上下文,也不在数组成员之间写逗号,所以我正在转换Json编写器并调用其writeValue()方法来处理这个问题 奇怪的是,这在问题中的示例上不起作用(同样也不需要序列化这些双精度),但在我的实际对象上起作用,它更复杂 享受
public class JacksonDoubleArrayTest
{
private DecimalFormat df = new DecimalFormat( "0.##E0" );
public class MyDoubleSerializer extends org.codehaus.jackson.map.ser.ScalarSerializerBase<Double>
{
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<String, Object> load() throws JsonParseException, JsonMappingException, IOException
{
ObjectMapper loader = new ObjectMapper();
return (Map<String, Object>)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() );
}
}
公共类JacksonDoubleArrayTest
{
私有DecimalFormat df=新的DecimalFormat(“0.##E0”);
公共类MyDoubleSerializer扩展org.codehaus.jackson.map.ser.ScalarSerializerBase
{
受保护的MyDoubleSerializer()
{
超级(双级);
}
@凌驾
public final void serializeWithType(双值,JsonGenerator jgen,SerializerProvider,TypeSerializer typeSer)引发IOException,
JsonGenerationException
{
序列化(值、jgen、提供程序);
}
@凌驾
public void serialize(双值、JsonGenerator jgen、SerializerProvider提供程序)抛出IOException、JsonGenerationException
{
if(Double.isNaN(值)| Double.isInfinite(值))
{
jgen.writeNumber(0);//因为在JSON中没有更好的替代方法
返回;
}
字符串x=df.format(值);
如果(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();
如果(jgen.getOutputContext().getCurrentIndex()>0)
{
x=“,”+x;
}
jgen.writeRaw(x);
}
@凌驾
公共JsonNode getSchema(SerializerProvider提供程序,类型typeHint)
{
返回createSchemaNo(“number”,true);
}
}
@抑制警告(“未选中”)
私有静态映射加载()抛出JsonParseException、JsonMappingException、IOException
{
ObjectMapper loader=新的ObjectMapper();
return(Map)loader.readValue(新文件(“x.json”)、Map.class);
}
@试验
public void test1()抛出JsonGenerationException、JsonMappingException、IOException
{
ObjectMapper mapper=新的ObjectMapper();
SimpleModule=新的SimpleModule(“StatsModule”,新版本(0,1,0,“alpha”);
addSerializer(Double.class,新的MyDoubleSerializer());
映射器注册表模块(模块);
String out=mapper.writeValueAsString(load());
//System.out.println(out.length());
}
}