2016-08-10 18 views
1

我試圖讓Gson沒有浮點爲多頭,而不是作爲雙打,因爲它defaultly做解析值:讓GSON解析整數,而不是作爲花車

Gson gson = new GsonBuilder() 
      .registerTypeAdapter(Object.class, (JsonDeserializer<Object>) (json, type, context) -> { 
       // we don't want integer values to be parsed as floats 
       String value = json.getAsJsonPrimitive().getAsString(); 
       if (value.matches("\\d+")) { 
        return Long.valueOf(value); 
       } else { 
        return context.deserialize(json, type); 
       } 
      }).create(); 
... 
gson.fromJson(payload); 

我只是想測試一下,渡過值包含.,如果不包含,則將其解析爲Long。否則使用默認的解析方法。

但是,當我放置斷點時,該方法從不會被調用。我想我以錯誤的方式註冊適配器。

EDIT1:Json可能包含帶有字符串,整數,雙精度和貼圖的列表。我需要一個通用解決方案。

EDIT2:我也試過品種.registerTypeAdapter(Number.class.registerTypeAdapter(Double.class沒有效果。還沒有叫。

回答

0

我找不到比完全覆蓋Gson函數更好的方法。這是相當黑客,但沒有其他解決方案似乎可以解決問題:

public class Gson { 

    private static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { 
     public <T> TypeAdapter<T> create(com.google.gson.Gson gson, TypeToken<T> type) { 
      return type.getRawType() == Object.class ? (TypeAdapter<T>) new LongObjectTypeAdapter(gson) : null; 
     } 
    }; 



    static { 
     try { 
      Field field = ObjectTypeAdapter.class.getDeclaredField("FACTORY"); 

      Field modifiersField = Field.class.getDeclaredField("modifiers"); 
      modifiersField.setAccessible(true); 
      modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); 

      field.setAccessible(true); 
      field.set(null, FACTORY); 

     } catch (Exception e) { 
      throw new IllegalStateException(e); 
     } 
    } 



    private com.google.gson.Gson gson = new com.google.gson.Gson(); 



    public <T> T fromJson(String payload, Class<T> c) { 
     return gson.fromJson(payload, c); 
    } 



    public String toJson(Object object) { 
     return gson.toJson(object); 
    } 



    public static class LongObjectTypeAdapter extends TypeAdapter<Object> { 

     private com.google.gson.Gson gson; 

     public LongObjectTypeAdapter(com.google.gson.Gson gson) { 
      this.gson = gson; 
     } 

     public Object read(JsonReader in) throws IOException { 
      JsonToken token = in.peek(); 

      switch (token) { 
       case BEGIN_ARRAY: 
        ArrayList list = new ArrayList(); 
        in.beginArray(); 

        while(in.hasNext()) { 
         list.add(this.read(in)); 
        } 

        in.endArray(); 
        return list; 
       case BEGIN_OBJECT: 
        LinkedTreeMap map = new LinkedTreeMap(); 
        in.beginObject(); 

        while(in.hasNext()) { 
         map.put(in.nextName(), this.read(in)); 
        } 

        in.endObject(); 
        return map; 
       case STRING: 
        return in.nextString(); 
       case NUMBER: 
        String value = in.nextString(); 
        if (value.contains(".")) { 
         return Double.valueOf(value); 
        } else { 
         return Long.valueOf(value); 
        } 

       case BOOLEAN: 
        return Boolean.valueOf(in.nextBoolean()); 
       case NULL: 
        in.nextNull(); 
        return null; 
       default: 
        throw new IllegalStateException(); 
      } 
     } 

     public void write(JsonWriter out, Object value) throws IOException { 
      if (value == null) { 
       out.nullValue(); 
      } else { 
       TypeAdapter typeAdapter = gson.getAdapter(value.getClass()); 
       if (typeAdapter instanceof LongObjectTypeAdapter) { 
        out.beginObject(); 
        out.endObject(); 
       } else { 
        typeAdapter.write(out, value); 
       } 
      } 
     } 
    } 
}