2013-06-13 13 views
13

मेरे पास अंदरूनी मूल्यों के साथ जेसन ऑब्जेक्ट है। और मैं इसे मानचित्र में deserialize करना चाहता हूँ। पूर्णांक को एक युगल में परिवर्तित करने के अलावा सबकुछ ठीक है। उदाहरण देखें: करने के लिएजीसन। पूर्णांक के रूप में पूर्णांक को deserialize और युगल के रूप में नहीं

{"id":1, "inner_obj":{"key":"value","num":666,"map":{"key":"value"}}} 

deserializes इस (map.toString()):

{id=1.0, inner_obj={key=value, num=666.0, map={key=value}}} 

वहाँ कुछ आसान तरीका "id" और "संख्या" deserialize करने के लिए पूर्णांक के रूप में और न डबल्स के रूप में है?

+0

यह भी देखें [यह उत्तर] (http://stackoverflow.com/a/43346123/179864) मैंने इसी तरह के प्रश्न के लिए लिखा था; पकड़ यह है कि आपको डेटा को 'ऑब्जेक्ट' के रूप में पार्स करना होगा और फिर आपको जो चाहिए उसे डालना होगा। – aditsu

+0

जैक्सन नक्शे के प्रकारों का पता लगाने में एक बेहतर काम करता है, और जीएसओएन की तुलना में कॉन्फ़िगर करना कहीं अधिक आसान है: https://github.com/FasterXML/jackson- डाटाबेस –

+0

सवाल जीएसन कार्यान्वयन के लिए स्पष्ट रूप से पूछा गया। कृपया सवाल से चिपके रहें। – Megakoresh

उत्तर

7

JSON में कोई पूर्णांक प्रकार नहीं है। 1 और 1.0 वही हैं। आपको अपने कोड में उस 1.0 से 1 को पार्स करने की आवश्यकता है। या आपको जेएसओएन को कुछ वीओ कक्षा में मैप करने और कक्षा के फ़ील्ड के प्रकार को स्पष्ट रूप से परिभाषित करने की आवश्यकता है, ताकि जीएसओएन आप जो खोज रहे हैं उसे समझ सकें।

+4

लेकिन जावा में इंटीग्रर्स और डबल्स हैं। और अगर मेरे पास इंटीजर फ़ील्ड "num" वाला क्लास है, तो इंटीजर को {"num": 1} को deserialize करना आसान है, लेकिन जब जीसन जेसन को मैप <स्ट्रिंग, ऑब्जेक्ट> को डिज़ाइन करता है तो यह डबल का उपयोग करने का इरादा रखता है। तो मैं इस दृष्टिकोण को अक्षम करने के तरीके की तलाश कर रहा हूं। – Moses

+0

@Moses एक मानचित्र को परिभाषित करता है <स्ट्रिंग, इंटीजर> –

+3

मानचित्र में न केवल पूर्णांक होना चाहिए। – Moses

2

JSON केवल एक ही संख्या प्रकार है और पार्सर को स्वचालित रूप से यह बताने का कोई तरीका नहीं है कि इसे किस प्रकार परिवर्तित करना है।

आप एक जोरदार टाइप किया वस्तु ग्राफ का उपयोग करने के लिए नहीं जा रहे हैं, तो JsonElement प्रकार का उपयोग करें:

JsonObject root = new Gson().fromJson(json, JsonObject.class); 
int num = root.getAsJsonObject("inner_obj").get("num").getAsInt(); 
1

यह मेरा कोड है

private static class MapDeserializer implements JsonDeserializer<Map<String,Object>> { 
    public Map<String,Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     Map<String,Object> m = new LinkedHashMap<String, Object>(); 
     JsonObject jo = json.getAsJsonObject(); 
     for (Entry<String, JsonElement> mx : jo.entrySet()){ 
      String key = mx.getKey(); 
      JsonElement v = mx.getValue(); 
      if(v.isJsonArray()){ 
       m.put(key, g.fromJson(v, List.class)); 
      }else if(v.isJsonPrimitive()){ 
       Number num = null; 
        try { 
         num = NumberFormat.getInstance().parse(v.getAsString()); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
       m.put(key,num); 
      }else if(v.isJsonObject()){ 
       m.put(key,g.fromJson(v, Map.class));  
      } 

     } 
     return m; 
    } 
} 

private static class ListDeserializer implements JsonDeserializer<List<Object>> { 
    public List<Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     List<Object> m = new ArrayList<Object>(); 
     JsonArray arr = json.getAsJsonArray(); 
     for (JsonElement jsonElement : arr) { 
      if(jsonElement.isJsonObject()){ 
       m.add(g.fromJson(jsonElement, Map.class)); 
      }else if(jsonElement.isJsonArray()){ 
       m.add(g.fromJson(jsonElement, List.class)); 
      }else if(jsonElement.isJsonPrimitive()){ 
       Number num = null; 
       try { 
        num = NumberFormat.getInstance().parse(jsonElement.getAsString()); 
       } catch (Exception e) { 
       } 
       m.add(num); 
      } 
     } 
     return m; 
    } 
} 

private static Gson g = new GsonBuilder().registerTypeAdapter(Map.class, new MapDeserializer()).registerTypeAdapter(List.class, new ListDeserializer()).setDateFormat("yyyy-MM-dd HH:mm:ss").serializeNulls().create(); 
1

नेस्टेड मानचित्र के लिए एक समाधान के लिए खोज कर दिया गया समस्या स्वयं और "이종은" ऊपर पहला जवाब था जो वास्तव में गैर तुच्छ उपयोग मामलों में मदद करता था।

के बाद से समाधान केवल संभाला संख्या ऊपर मैं समाधान अद्यतन स्ट्रिंग और भी बूलियन्स के लिए सामान्य पार्स क्षमता प्रदान करने के लिए नीचे दिए गए अद्यतन कोड देखें:

private static class MapDeserializer implements JsonDeserializer<Map<String, Object>> { 

    public Map<String, Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     Map<String, Object> m = new LinkedHashMap<String, Object>(); 
     JsonObject jo = json.getAsJsonObject(); 
     for (Entry<String, JsonElement> mx : jo.entrySet()) { 
      String key = mx.getKey(); 
      JsonElement v = mx.getValue(); 
      if (v.isJsonArray()) { 
       m.put(key, g.fromJson(v, List.class)); 
      } else if (v.isJsonPrimitive()) { 
       Number num = null; 
       ParsePosition position=new ParsePosition(0); 
       String vString=v.getAsString(); 
       try { 
        num = NumberFormat.getInstance(Locale.ROOT).parse(vString,position); 
       } catch (Exception e) { 
       } 
       //Check if the position corresponds to the length of the string 
       if(position.getErrorIndex() < 0 && vString.length() == position.getIndex()) { 
        if (num != null) { 
        m.put(key, num); 
        continue; 
        } 
       } 
       JsonPrimitive prim = v.getAsJsonPrimitive(); 
       if (prim.isBoolean()) { 
        m.put(key, prim.getAsBoolean()); 
       } else if (prim.isString()) { 
        m.put(key, prim.getAsString()); 
       } else { 
        m.put(key, null); 
       } 

      } else if (v.isJsonObject()) { 
       m.put(key, g.fromJson(v, Map.class)); 
      } 

     } 
     return m; 
    } 
} 

private static class ListDeserializer implements JsonDeserializer<List<Object>> { 

    public List<Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     List<Object> m = new ArrayList<Object>(); 
     JsonArray arr = json.getAsJsonArray(); 
     for (JsonElement jsonElement : arr) { 
      if (jsonElement.isJsonObject()) { 
       m.add(g.fromJson(jsonElement, Map.class)); 
      } else if (jsonElement.isJsonArray()) { 
       m.add(g.fromJson(jsonElement, List.class)); 
      } else if (jsonElement.isJsonPrimitive()) { 
       Number num = null; 
       try { 
        num = NumberFormat.getInstance().parse(jsonElement.getAsString()); 
       } catch (Exception e) { 
       } 
       if (num != null) { 
        m.add(num); 
        continue; 
       } 
       JsonPrimitive prim = jsonElement.getAsJsonPrimitive(); 
       if (prim.isBoolean()) { 
        m.add(prim.getAsBoolean()); 
       } else if (prim.isString()) { 
        m.add(prim.getAsString()); 
       } else { 
        m.add(null); 
       } 
      } 
     } 
     return m; 
    } 
} 

private static Gson g = new GsonBuilder().registerTypeAdapter(Map.class, new MapDeserializer()).registerTypeAdapter(List.class, new ListDeserializer()).setDateFormat("yyyy-MM-dd HH:mm:ss").create(); 
+0

इससे मुझे बहुत मदद मिली! मैं बस एक छोटी सी बग एक बिंदु पसंद करेंगे। ListDeserializer में आपको कोशिश करें {} ब्लॉक में "m.add (num)" को हटा देना चाहिए, क्योंकि इसे कोशिश/पकड़ने के बाद भी जोड़ा जाएगा। यदि आप कोड का उपयोग करते हैं, तो यह परिणामस्वरूप प्रत्येक नंबर को दो बार जोड़ देगा। – peanutman

+0

धन्यवाद ने अभी उदाहरण अपडेट किया है। –

+0

मुझे लगता है कि आप gson के स्थिर उदाहरण की आवश्यकता से बचने के लिए g.fromJson (...) को संदर्भ.deserialize (...) में कॉल को प्रतिस्थापित कर सकते हैं (कम से कम यह मेरे लिए gson 2.6.2 के लिए काम करता है) – David

0

यहाँ मेरी उदाहरण है, पहले भाग परिभाषा है कक्षा का एक int प्रकार क्षेत्र है।

import com.google.api.client.util.Key; 

public class Folder { 

    public static final String FIELD_NAME_CHILD_COUNT = "childCount"; 

    @Key(FIELD_NAME_CHILD_COUNT) 
    public final int childCount; 

    public Folder(int aChildCount) { 
     childCount = aChildCount; 
    } 
} 

फिर टाइप एडाप्टर को जीएसन में जावा ऑब्जेक्ट में कनवर्ट करने के लिए टाइप एडाप्टर।

GsonBuilder gsb = new GsonBuilder(); 

gsb.registerTypeAdapter(Folder.class, new JsonDeserializer<Folder>() { 

      @Override 
      public Folder deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 

       int value = json.getAsJsonObject().get("childCount").getAsJsonPrimitive().getAsInt(); 

       return new Folder(value); 

      } 
     } 
); 

तीसरा हिस्सा परीक्षण डेटा है, और यह काम करता है।

String gsonData = new String("\"folder\":{\"childCount\":0}"); 
0

संभव ClassCastException से बचने के लिए, यह पहली Number को कास्ट करने के लिए बेहतर है। निम्नलिखित कोड map को जेएसओएन से Map के रूप में कोई जेनेरिक के साथ deserialized किया गया था।

int numberOfPages = ((Number) map.get("number_of_pages")).intValue(); 
संबंधित मुद्दे