2011-09-04 2 views
5

Я кодирую сложную структуру карты с массивами двойных значений. Высокая точность не важна и размер вывода, поэтому я пытаюсь получить инструмент JSON (в этом случае Джексон) для сериализации двойных значений с использованием предоставленного DecimalFormat.jackson - json кодирование удвоений с контролируемой точностью

Ниже мой лучший выстрел, но это не удается, поскольку сериализатор не захватывается с помощью объекта картографа для кодирования массива:

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)); 
    } 
} 

Выход есть:

{ «Тест» : [1.1111111111,1.315143204964E12}

Что я искал:

{ "тест": [1.32E12, 1.11E0]}

Любые идеи?

Кроме того, мне не нравится, когда нужно создать строку, а запись - как необработанная - есть ли способ, которым я могу передать StringBuffer в DecimalFormat, чтобы сделать это?

Благодаря

ответ

4

Успели решить эту проблему, путем заимствования из встроенного сериализатором для Double.

Это немного взломать, потому что writeRaw() не заботится о контексте и не пишет запятую между элементами массива, поэтому я бросаю Json writer и вызываю свой метод 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()); 
    } 
}