जैक्सन को बिना कास्टिंग के JrayNode को ArrayNode में कैसे बदलना है?


116

मैं अपनी JSON लाइब्रेरी को org.json से जैक्सन में बदल रहा हूं और मैं निम्नलिखित कोड को माइग्रेट करना चाहता हूं:

JSONObject datasets = readJSON(new URL(DATASETS));
JSONArray datasetArray =  datasets.getJSONArray("datasets");

अब जैक्सन में मेरे पास निम्नलिखित हैं:

ObjectMapper m = new ObjectMapper();
JsonNode datasets = m.readTree(new URL(DATASETS));      
ArrayNode datasetArray = (ArrayNode)datasets.get("datasets");

हालांकि मुझे वहां कास्ट पसंद नहीं है, क्या ए के लिए संभावना है ClassCastException? वहाँ के लिए एक विधि के बराबर है getJSONArrayमें org.jsonइतना है कि मैं इस मामले में उचित त्रुटि हैंडलिंग है यह एक सरणी नहीं है?


दुर्भाग्य से मैं पूर्ण मैपिंग का उपयोग नहीं कर सकता क्योंकि डेटा फ़ील्ड के नाम तय नहीं करता है।
कोनराड होफनर

1
यदि फ़ील्ड नाम एक सीमित सेट से आते हैं, तो आप उन सभी की विशेषता वाले एक वर्ग को परिभाषित करना चाह सकते हैं, और FAIL_ON_UNKNOWN_PROPERTIESअप्रयुक्त क्षेत्र की सुविधा का उपयोग केवल अप्रयुक्त क्षेत्रों में वापस आने के लिए कर सकते हैं। लेकिन यह निश्चित रूप से केवल एक विकल्प है यदि फ़ील्ड नाम सेट अपेक्षाकृत सीमित है।
fvu

हम्म मुझे लगता है कि यह समाधान मेरे मामले में सबसे अच्छा फिट नहीं है, लेकिन मैं इसे याद रखूँगा अगर मुझे एक सीमित सेट के साथ समस्या होगी जो पहले से ज्ञात है!
कोनराड होफनर

जवाबों:


247

हां, जैक्सन मैनुअल पार्सर डिजाइन अन्य पुस्तकालयों से काफी अलग है। विशेष रूप से, आप देखेंगे कि JsonNodeअधिकांश कार्य ऐसे हैं जिन्हें आप आमतौर पर अन्य एपीआई के सरणी नोड्स के साथ जोड़ते हैं। जैसे, आपको ArrayNodeउपयोग करने के लिए एक कास्ट करने की आवश्यकता नहीं है । यहाँ एक उदाहरण है:

JSON:

{
    "objects" : ["One", "Two", "Three"]
}

कोड:

final String json = "{\"objects\" : [\"One\", \"Two\", \"Three\"]}";

final JsonNode arrNode = new ObjectMapper().readTree(json).get("objects");
if (arrNode.isArray()) {
    for (final JsonNode objNode : arrNode) {
        System.out.println(objNode);
    }
}

आउटपुट:

"एक"
"दो"
"तीन"

isArrayयह सत्यापित करने के उपयोग पर ध्यान दें कि नोड वास्तव में पुनरावृत्ति करने से पहले एक सरणी है। चेक आवश्यक नहीं है यदि आप अपने डेटा संरचना में पूरी तरह से आश्वस्त हैं, लेकिन इसके उपलब्ध होने के लिए आपको इसकी आवश्यकता होनी चाहिए (और यह अधिकांश अन्य JSON पुस्तकालयों से अलग नहीं है)।


2
आपने मुझे घंटों बचाया। धन्यवाद!
इगोर मोरीस

क्या मुझे पता है कि "अंतिम" लाइन में "अंतिम JsonNode objNode: arrNode)" का उपयोग क्यों किया जाता है?
एंथोनी विनय

5

Java 8 में आप इसे इस तरह से कर सकते हैं:

import java.util.*;
import java.util.stream.*;

List<JsonNode> datasets = StreamSupport
    .stream(datasets.get("datasets").spliterator(), false)
    .collect(Collectors.toList())

1

क्या org.json मेंJJSONArray के बराबर कोई विधि है ताकि मेरे पास एक एरर न होने की स्थिति में उचित त्रुटि हैंडलिंग हो?

यह आपके इनपुट पर निर्भर करता है; यानी वह सामान जो आप URL से प्राप्त करते हैं। यदि "डेटासेट" विशेषता का मान सादे सरणी के बजाय एक साहचर्य सरणी है, तो आपको एक मिल जाएगा ClassCastException

लेकिन फिर, आपके पुराने संस्करण की शुद्धता भी इनपुट पर निर्भर करती है। उस स्थिति में जहां आपका नया संस्करण एक फेंकता है ClassCastException, पुराना संस्करण फेंक देगा JSONException। संदर्भ: http://www.json.org/javadoc/org/json/JSONObject.html#getJSONArray(java.lang.String)


आह ठीक है तो मैं सिर्फ एक ClassCastException पकड़ सकता है, धन्यवाद! मेरे स्वाद के लिए यह एक विशिष्ट JsonException होने की तुलना में थोड़ा कम सुरुचिपूर्ण है, लेकिन अगर यह संभव नहीं है तो यह अभी भी अच्छा है।
कोनराड होफनर

0

मैं उस दिन के अंत में मानूंगा कि आप डेटा को ArrayNode में पुनरावृत्त करके उपभोग करना चाहते हैं। उसके लिए:

Iterator<JsonNode> iterator = datasets.withArray("datasets").elements();
while (iterator.hasNext()) 
        System.out.print(iterator.next().toString() + " "); 

या यदि आप धाराओं और लंबो कार्यों में हैं:

import com.google.common.collect.Streams;
Streams.stream(datasets.withArray("datasets").elements())
    .forEach( item -> System.out.print(item.toString()) )
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.