2012-06-20 5 views
12

Wenn ich Gson verwenden, um ein Objekt zu serialisieren, die nahe einem Doppel Wert enthält es wird auf Null die wissenschaftliche E-Notation:ausschalten wissenschaftliche Schreibweise in Gson Doppel Serialisierung

{"doublevaule":5.6E-4} 

Wie kann ich sagen, Gson zu erzeugen

{"doublevaule":0.00056} 

statt? Ich kann einen benutzerdefinierten JsonSerializer implementieren, aber es gibt ein JsonElement zurück. Ich müsste ein JsonPrimitive zurückgeben, das ein Double enthält, das keine Kontrolle darüber hat, wie das serialisiert wird.

Danke!

+4

Warum das ein Problem ist? Die wissenschaftliche Notation ist in JSON gültig, und alles, was JSON behandelt, sollte in der Lage sein, das korrekt zu analysieren (auf genau den gleichen Wert, als ob die wissenschaftliche Notation nicht verwendet würde). –

+0

Ich streite damit nicht, du hast recht Joachim. Trotzdem möchte ich, dass mein JSON keine wissenschaftlichen Notationen enthält. Ist das mit GSon machbar? – konstantin

+0

Ich habe genau das gleiche Problem, einfach aufgrund der Tatsache, dass ich einen gebrochenen JSON-Consumer habe, der nicht mit Exponenten umgehen kann. Mir ist klar, dass die * echte * Lösung darin besteht, den Verbraucher zu sortieren, aber manchmal liegt das außerhalb unserer Kontrolle. Daher denke ich, dass dies eine vernünftige (wenn nicht ungewöhnliche) Anforderung ist –

Antwort

2

Sie könnten versuchen, erstreckt JsonWriter und überwiegenden the method value(double)

Es scheint nicht, wie dies zu modifizierenden gebaut werden (Sie ziemlich viel brauchen, den vorhandenen Code zu duplizieren), aber es sollte möglich sein, zu erhalten es funktioniert.

Leider sehe ich keinen anderen Grund, das Ausgabeformat zu beeinflussen.

+0

Dies ist der richtige Ansatz, aber es wird wahrscheinlich viel doppelten Code erfordern. JsonWriter wurde nicht für diese Art der Erweiterbarkeit entwickelt und es fehlen die notwendigen Hooks. –

9

Warum gibt es keinen neuen Serialiser für Double? (Sie müssen Ihr Objekt wahrscheinlich neu schreiben, um Double anstelle von double zu verwenden).

Dann in dem Serializer können Sie zu einem BigDecimal, konvertieren und spielen mit der Waage usw.

z.B.

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

Die oben machen wird (sagen wir) 9.166666E-6 als 0.000009166666

1

Erstellen eines benutzerdefinierten Serializer für 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()); 
    } 
}); 

Vorher: { "Betrag": 1.0E9}

Nach: {"Betrag": "1000000000"}

Nicht gerade perfekt, da es ein String im JSON ist.

2

Intern Gson verwendet Nummer # toString so müssen wir nur noch eine neue Instanz einer Anzahl erstellen:

.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

Eine kleine Änderung auf 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); 
    } 
} 
Verwandte Themen