2012-06-20 44 views
12

Cuando uso Gson para serializar un objeto que contiene un doble valor cercano a cero que está utilizando el científico E-notación:apagar la notación científica en Gson doble serialización

{"doublevaule":5.6E-4} 

¿Cómo le digo Gson para generar

{"doublevaule":0.00056} 

¿cambio? Puedo implementar un JsonSerializer personalizado, pero devuelve un JsonElement. Tendría que devolver un JsonPrimitive que contenga un doble sin control sobre cómo se serializa.

Gracias!

+4

¿Por qué es un problema? La notación científica es válida en JSON y cualquier cosa que maneje JSON debería ser capaz de analizar eso correctamente (exactamente el mismo valor que si no se utilizara la notación científica). –

+0

No discuto eso, tienes razón, Joachim. Sin embargo, me gustaría que mi JSON no contenga anotaciones científicas. ¿Es eso factible con GSon? – konstantin

+0

Tengo exactamente el mismo problema, simplemente debido al hecho de que tengo un consumidor JSON roto que no puede manejar exponentes. Me doy cuenta de que la solución * real * es ordenar al consumidor, pero a veces eso está fuera de nuestro control. Por lo tanto, creo que este es un requisito razonable (aunque inusual) –

Respuesta

2

Usted podría intentar extender JsonWriter y primordial the method value(double)

No parece que ser construido para ser modificada, como (usted más o menos necesidad de duplicar el código existente), pero debería ser posible conseguir está funcionando.

Lamentablemente no veo otra razón para influir en el formato de salida.

+0

Este es el enfoque correcto, pero probablemente requerirá una gran cantidad de código duplicado. JsonWriter no fue diseñado para este tipo de extensibilidad y carece de los ganchos necesarios. –

9

¿Por qué no proporciona un nuevo serializador para Double? (Es probable que tenga que volver a escribir su objeto para usar Double en lugar de double).

Luego, en el serializador se puede convertir en una BigDecimal, y jugar con la escala etc.

por ejemplo,

GsonBuilder gsonBuilder = new GsonBuilder(); 
    gsonBuilder.registerTypeAdapter(Double.class, new JsonSerializer<Double>() { 
     @Override 
     public JsonElement serialize(final Double src, final Type typeOfSrc, final JsonSerializationContext context) { 
      BigDecimal value = BigDecimal.valueOf(src); 

      return new JsonPrimitive(value); 
     } 
    }); 

    gson = gsonBuilder.create(); 

Lo anterior hará que (por ejemplo) como 9.166666E-60.000009166666

1

Crear un serializador personalizado para Double

GsonBuilder gsonBuilder = new GsonBuilder(); 
gsonBuilder.registerTypeAdapter(Double.class, new JsonSerializer<Double>() { 
    @Override 
    public JsonElement serialize(Double originalValue, Type typeOf, JsonSerializationContext context) { 
     BigDecimal bigValue = BigDecimal.valueOf(originalValue); 

     return new JsonPrimitive(bigValue.toPlainString()); 
    } 
}); 

Antes: { "Cantidad": 1.0E9}

Después de: {"Cantidad": "1000000000"}

No es exactamente perfecto, ya que es una cadena en el JSON.

2

Internamente GSON utiliza el número # toString tan sólo tenemos que crear una nueva instancia de un número:

.registerTypeAdapter(Double.class, new JsonSerializer<Double>() { 
    @Override 
    public JsonElement serialize(final Double src, final Type typeOfSrc, final JsonSerializationContext context) { 

     Number n = new Number() { 

      @Override 
      public long longValue() { 
       return 0; 
      } 

      @Override 
      public int intValue() { 
       return 0; 
      } 

      @Override 
      public float floatValue() { 
       return 0; 
      } 

      @Override 
      public double doubleValue() { 
       return 0; 
      } 

      @Override 
      public String toString() { 
       return new BigDecimal(src).toPlainString(); 
      } 

     }; 

     return new JsonPrimitive(n); 
    } 
}) 
2

Un cambio menor en Brian Agnew's answer:

public class DoubleJsonSerializer implements JsonSerializer<Double> { 
    @Override 
    public JsonElement serialize(final Double src, final Type typeOfSrc, final JsonSerializationContext context) { 
     BigDecimal value = BigDecimal.valueOf(src); 
     try { 
      value = new BigDecimal(value.toBigIntegerExact()); 
     } catch (ArithmeticException e) { 
      // ignore 
     } 

     return new JsonPrimitive(value); 
    } 
} 
Cuestiones relacionadas