2011-06-13 13 views
11

नीचे दिखाया गया कोड अच्छी तरह से काम करता है जब JSON ऑब्जेक्ट में jsonKey होता है क्योंकि यह विधि को पास किया गया था। मुझे आश्चर्य है ... अगर किसी मामले को एक कुंजी के असंवेदनशील प्रतिनिधित्व के लिए आवंटित मूल्य प्राप्त करने का कोई तरीका है?जीएसओएन: जेसन से केस असंवेदनशील तत्व कैसे प्राप्त करें?

उदाहरण:

public String getOutputEventDescription(JsonElement outputEvent) throws ParserException { 
    return retrieveString(outputEvent, DESCRIPTION); 
} 

परवाह किए बिना काम करना चाहिए कि क्या वर्णन के रूप में "विवरण", "विवरण" या "विवरण" परिभाषित किया गया है

protected String retrieveString(JsonElement e, String jsonKey) throws ParserException { 

JsonElement value = e.getAsJsonObject().get(jsonKey); 

if (value == null) { 
    throw new ParserException("Key not found: " + jsonKey); 
} 

if (value.getAsString().trim().isEmpty()) { 
    throw new ParserException("Key is empty: " + jsonKey); 
} 

return e.getAsJsonObject().get(jsonKey).getAsString(); 
} 

उत्तर

5

दुर्भाग्य से वहाँ होना प्रतीत नहीं होता है एक ऐसा करने के लिए वर्तमान कार्यान्वयन में रास्ता। यदि आप जीसन स्रोत को देखते हैं और अधिक विशेष रूप से जेसनऑब्जेक्ट कार्यान्वयन पर आप देखेंगे कि अंतर्निहित डेटा संरचना एक लिंक हैश नक्शा है। कॉल कॉल बस मानचित्र पर मिलने का आह्वान करता है, जो बदले में हैश कोड का उपयोग करता है और जिस वस्तु को आप ढूंढ रहे हैं उसे ढूंढने के लिए अपनी कुंजी के तरीके के बराबर होता है।

आपके लिए कुछ नामकरण सम्मेलनों को लागू करने का एकमात्र तरीका है। सबसे आसान तरीका सभी चाबियों को लोअरकेस पर मजबूर करना होगा। यदि आपको मिश्रित केस कुंजी की आवश्यकता है तो आपको और अधिक कठिनाई होगी और केवल jsonKey.toLowerCase() को कॉल करने के बजाय कुंजी को बदलने के लिए एक अधिक परिष्कृत एल्गोरिदम लिखना होगा।

8

दुर्भाग्यवश, को GsonBuilder के साथ पंजीकृत करना बहुत अच्छा नहीं होगा, क्योंकि यह केवल विपरीत दिशा से विपरीत दिशा में अनुवाद करता है: जावा फ़ील्ड नाम से JSON तत्व नाम तक। यह आपके उद्देश्यों के लिए उचित रूप से उपयोग नहीं किया जा सकता है।

(विस्तार में:

अनुवाद अनुरोध के परिणाम FieldNamingStrategy.translateName(Field), जहां अनुवाद नाम एक JsonObject से जुड़े JSON तत्व है, जो एक LinkedHashMap<String, JsonElement> है प्राप्त करने के लिए प्रयोग किया जाता है पर समाप्त होता है, members कहा जाता है, मानचित्रण JSON तत्व नाम उनके संबद्ध मूल्यों के लिए। अनुवाद नाम members की get(String) विधि के लिए पैरामीटर के रूप में प्रयोग किया जाता है, और Gson कोई तंत्र के लिए यह अंतिम कॉल केस संवेदी किए जाने के लिए प्रदान करता है।

members नक्शाके लिए कॉल के साथ से भर जाता है, Streams.parseRecursive(JsonReader) से बना है, JSON तत्व नाम JsonReader से 'सदस्यों' की कुंजी के रूप में उपयोग किया गया है। (JsonReader वर्णों का उपयोग जेएसओएन में ठीक उसी तरह करता है, जहां अपवाद चरित्र '\' पाया जाता है।) इस कॉल स्टैक के दौरान, जीसन members को बदलने के लिए उपयोग की जाने वाली कुंजियों के लिए कोई तंत्र प्रदान नहीं करता है, उदाहरण के लिए, सभी निचले मामले या सभी ऊपरी मामले बनाया जाना चाहिए।

उसी तरह से एक FieldNamingPolicy काम करता है।)

एक उचित समाधान बस, एक कस्टम deserializer उपयोग करने के लिए निम्नलिखित लाइनों के साथ हो सकता है।

input.json:

[ 
{"field":"one"}, 
{"Field":"two"}, 
{"FIELD":"three"}, 
{"fIElD":"four"} 
] 

फू।जावा:

import java.io.FileReader; 
import java.lang.reflect.Type; 
import java.util.Map.Entry; 

import com.google.gson.Gson; 
import com.google.gson.GsonBuilder; 
import com.google.gson.JsonDeserializationContext; 
import com.google.gson.JsonDeserializer; 
import com.google.gson.JsonElement; 
import com.google.gson.JsonObject; 
import com.google.gson.JsonParseException; 

public class Foo 
{ 
    public static void main(String[] args) throws Exception 
    { 
    GsonBuilder gsonBuilder = new GsonBuilder(); 
    gsonBuilder.registerTypeAdapter(MyClass.class, new MyTypeAdapter()); 
    Gson gson = gsonBuilder.create(); 
    MyClass[] myObjects = gson.fromJson(new FileReader("input.json"), MyClass[].class); 
    System.out.println(gson.toJson(myObjects)); 
    } 
} 

class MyClass 
{ 
    String field; 
} 

class MyTypeAdapter implements JsonDeserializer<MyClass> 
{ 
    @Override 
    public MyClass deserialize(JsonElement json, Type myClassType, JsonDeserializationContext context) 
     throws JsonParseException 
    { 
    // json = {"field":"one"} 
    JsonObject originalJsonObject = json.getAsJsonObject(); 
    JsonObject replacementJsonObject = new JsonObject(); 
    for (Entry<String, JsonElement> elementEntry : originalJsonObject.entrySet()) 
    { 
     String key = elementEntry.getKey(); 
     JsonElement value = originalJsonObject.get(key); 
     key = key.toLowerCase(); 
     replacementJsonObject.add(key, value); 
    } 
    return new Gson().fromJson(replacementJsonObject, MyClass.class); 
    } 
} 

वैकल्पिक रूप से, आप पहली बार कच्चे JSON संसाधित कर सकते हैं सब कम या सभी ऊपरी एक ही मामला है तत्व नामों में से सभी को बदलने के लिए,। फिर, बदले गए JSON को deserialization के लिए जीसन पास करें। यह निश्चित रूप से JSON प्रसंस्करण धीमा कर देगा।

यदि आप अपनी परियोजना के लिए जीसन कोड बदल सकते हैं, तो शायद सबसे कुशल परिणाम के लिए बदलने का हिस्सा में name = nextString((char) quote); पर कॉल करना है। चूंकि nextString(char) का उपयोग JSON तत्व मान प्राप्त करने के लिए भी किया जाता है, इसलिए शायद मैं नाम प्राप्त करने के लिए इसकी प्रतिलिपि बनाउंगा, और फिर तत्वों के नाम को सभी निचले या सभी ऊपरी मामले में बल देने के लिए छोटे बदलाव करें। बेशक, यह दृष्टिकोण आपके प्रोजेक्ट को जीसन की एक रिलीज में लॉक करता है, अन्यथा आपको एक नई जीसन रिलीज में अपग्रेड करने के लिए इस बदलाव को दोहराना होगा।

Jackson के साथ, स्थिति दुर्भाग्य से समान दिखाई देती है। PropertyNamingStrategy के साथ अनुवाद दुर्भाग्यवश वैसे ही काम करते हैं: वे जावा फ़ील्ड नाम से JSON तत्व नाम में अनुवाद करते हैं। उपलब्ध JsonParser.Feature परिवर्तनों में से कोई भी JSON तत्व नाम को सभी ऊपरी या सभी निचले मामले में बल देने के लिए JsonParser को कस्टमाइज़ नहीं करेगा।

6

मुझे इसी तरह के मुद्दे का सामना करना पड़ा। मैंने इस मुद्दे को हल करने के लिए ऐसा किया। (सभी कुंजियों को उनके संबंधित लोअरकेस संस्करण के साथ बदल दिया और मिलान वर्ग में सभी निचले केस फ़ील्ड थे)। उम्मीद है की यह मदद करेगा।

input = input.replaceAll("\\s",""); 
     Matcher m = Pattern.compile("\"\\b\\w{1,}\\b\"\\s*:").matcher(input); 
     StringBuilder sanitizedJSON = new StringBuilder(); 
     int last = 0; 
     while (m.find()) { 
      sanitizedJSON.append(input.substring(last, m.start())); 
      sanitizedJSON.append(m.group(0).toLowerCase()); 
      last = m.end(); 
     } 
     sanitizedJSON.append(input.substring(last)); 

     input = sanitizedJSON.toString(); 
+1

यह बहुत अच्छा काम करता है सिवाय इसके कि मुझे यकीन नहीं है कि आप सभी रिक्त स्थान क्यों हटा रहे हैं। – Rooster242

संबंधित मुद्दे