2012-06-20 133 views
12

當我使用GSON序列化,它包含一個雙值接近它採用科學的E-符號零對象:關掉科學記數法中GSON雙系列化

{"doublevaule":5.6E-4} 

我如何告訴GSON產生

{"doublevaule":0.00056} 

取而代之?我可以實現一個自定義的JsonSerializer,但它返回一個JsonElement。我將不得不返回一個JsonPrimitive,其中包含一個無法控制序列化的double的JsonPrimitive。

謝謝!

+4

這是爲什麼有問題?科學記數法在JSON中是有效的,處理JSON的任何東西都應該能夠正確解析(如果沒有使用科學記數法,則完全相同的值)。 –

+0

我不會與此爭辯,你是對的Joachim。不過,我希望我的JSON不要包含科學記號。這對GSon來說可行嗎? – konstantin

+0

我有完全相同的問題,只是由於我有一個不能處理指數的JSON消費者。我意識到*真正的*修正是對消費者進行排序,但有時這是我們無法控制的。因此我認爲這是一個合理的(如果不尋常的)要求 –

回答

2

你可以嘗試擴大JsonWriter和壓倒一切的the method value(double)

它似乎並沒有建立這樣的修改(你非常需要複製現有的代碼),但它應該是可能得到它工作。

不幸的是我看不到其他原因影響輸出格式。

+0

這是正確的方法,但它可能需要大量重複的代碼。 JsonWriter不是爲這種可擴展性而設計的,並且缺乏必要的鉤子。 –

9

爲什麼不提供一個新的序列號爲Double? (您可能必須重寫您的對象才能使用Double而不是double)。

然後在串行器,你可以轉換爲BigDecimal,並與規模等

例如玩

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

以上將呈現(說)9.166666E-6作爲0.000009166666

1

創建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()); 
    } 
}); 

自定義序列之前:{ 「金額」:1.0E9}

後: {「金額」:「1000000000」}

不完全完美,因爲它是JSON中的一個字符串。

2

內部GSON使用號碼#的toString所以我們只需要創建一個數的新實例:

.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

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