2014-07-19 6 views
5

मुझे लगता है कि वस्तुओं की एक json सरणी शामिल एक फ़ाइल है:उपयोग जैक्सन स्ट्रीम करने के लिए पार्स Json का एक सरणी ऑब्जेक्ट्स

[ { "test1": "abc" }, { "test2": [1, 2, 3] } ]

मैं उपयोग का उपयोग करने के जैक्सन के JsonParser इस फ़ाइल से एक InputStream लेने के लिए, और हर कॉल पर .next करने के लिए(), मैं इसे सरणी से एक ऑब्जेक्ट प्रदान करना चाहते हैं इच्छा जब तक यह वस्तुओं से बाहर नहीं हो जाता है या विफल रहता है।

क्या यह संभव है?

केस का उपयोग करें: मेरे पास एक बड़ी फ़ाइल है जिसमें एक जेसन सरणी है जिसमें विभिन्न स्कीमा के साथ बड़ी संख्या में ऑब्जेक्ट हैं। मैं स्मृति में सब कुछ लोड करने से बचने के लिए एक समय में एक वस्तु प्राप्त करना चाहता हूं।

संपादित करें:

मैं पूरी तरह से उल्लेख करना भूल गया। मेरा इनपुट एक स्ट्रिंग है जो समय के साथ जोड़ा जाता है। यह धीरे-धीरे समय के साथ जेसन जमा करता है। मैं स्ट्रिंग से पार्स ऑब्जेक्ट को निकालने के ऑब्जेक्ट द्वारा ऑब्जेक्ट को पार्स करने में सक्षम होने की उम्मीद कर रहा था।

लेकिन मुझे लगता है कि इससे कोई फर्क नहीं पड़ता! मैं इसे मैन्युअल रूप से तब तक कर सकता हूं क्योंकि jsonParser स्ट्रिंग में इंडेक्स वापस कर देगा।

उत्तर

10

जो आप खोज रहे हैं उसे Jackson Streaming API कहा जाता है। जैक्सन स्ट्रीमिंग एपीआई का उपयोग करके एक कोड स्निपेट यहां दिया गया है जो आपको प्राप्त करने में आपकी सहायता कर सकता है।

JsonFactory factory = new JsonFactory(); 
JsonParser parser = factory.createJsonParser(new File(yourPathToFile)); 

JsonToken token = parser.nextToken(); 
if (token == null) { 
    // return or throw exception 
} 

// the first token is supposed to be the start of array '[' 
if (!JsonToken.START_ARRAY.equals(token)) { 
    // return or throw exception 
} 

// iterate through the content of the array 
while (true) { 

    token = parser.nextToken(); 
    if (!JsonToken.START_OBJECT.equals(token)) { 
     break; 
    } 
    if (token == null) { 
     break; 
    } 

    // parse your objects by means of parser.getXxxValue() and/or other parser's methods 

} 
20

हाँ, आप एक ObjectMapper का उपयोग कर भाग-स्ट्रीमिंग-पार्ट-वृक्ष की मॉडल प्रसंस्करण शैली की इस तरह प्राप्त कर सकते हैं:

ObjectMapper mapper = new ObjectMapper(); 
JsonParser parser = mapper.getFactory().createParser(new File(...)); 
if(parser.nextToken() != JsonToken.START_ARRAY) { 
    throw new IllegalStateException("Expected an array"); 
} 
while(parser.nextToken() == JsonToken.START_OBJECT) { 
    // read everything from this START_OBJECT to the matching END_OBJECT 
    // and return it as a tree model ObjectNode 
    ObjectNode node = mapper.readTree(parser); 

    // do whatever you need to do with this object 
} 

parser.close(); 
+1

अरे इयान, लगभग 2 वर्षों के बाद यह कोड वास्तव में अभी भी काम करता है और मेरा दिन बचाता है। बस पुष्टि करने की कोशिश कर रहा है, हर बार मैपर पढ़ने वाले पेड़ को तब तक करता है जब तक कि यह शुरू नहीं हुआ END_OBJECT टोकन मैचों में, पार्सर का "कर्सर" भी सही हो गया है? इसलिए यदि मैं थोड़ी देर के बाद सही 'parser.nextToken()' करता हूं, तो मुझे अभी पढ़ने के बाद अगला ऑब्जेक्ट पढ़ना चाहिए, सही? –

+1

@JamesJiang सही। 'ReadTree'' को 'START_OBJECT' पर स्थित एक पार्सर दिया गया है, जब तक कि वह मिलान 'END_OBJECT' तक पहुंच न जाए, तब तक पार्सर से ईवेंट का उपभोग करेगा और उस पर स्थित पार्सर को छोड़ देगा। –

1

यह एक देर से जवाब इयान रॉबर्ट्स के जवाब पर आधारित है, है। यदि आप दस्तावेज़ में घोंसला रखते हैं तो आप प्रारंभ स्थिति को ढूंढने के लिए जेसन पॉइंटर का भी उपयोग कर सकते हैं। यह प्रारंभ बिंदु पर जाने के लिए थोड़ा बोझिल स्ट्रीमिंग टोकन दृष्टिकोण को कस्टम कोडिंग से बचाता है। इस मामले में, बेसपैथ "/" है, लेकिन यह कोई रास्ता हो सकता है जो जेसन पॉइंटर समझता है।

Path sourceFile = Paths.get("/path/to/my/file.json"); 
// Point the basePath to a starting point in the file 
JsonPointer basePath = JsonPointer.compile("/"); 
ObjectMapper mapper = new ObjectMapper(); 
try (InputStream inputSource = Files.newInputStream(sourceFile); 
    JsonParser baseParser = mapper.getFactory().createParser(inputSource); 
    JsonParser filteredParser = new FilteringParserDelegate(baseParser, 
        new JsonPointerBasedFilter(basePath), false, false);) { 
    // Call nextToken once to initialize the filteredParser 
    JsonToken basePathToken = filteredParser.nextToken(); 
    if (basePathToken != JsonToken.START_ARRAY) { 
     throw new IllegalStateException("Base path did not point to an array: found " 
             + basePathToken); 
    } 
    while (filteredParser.nextToken() == JsonToken.START_OBJECT) { 
     // Parse each object inside of the array into a separate tree model 
     // to keep a fixed memory footprint when parsing files 
     // larger than the available memory 
     JsonNode nextNode = mapper.readTree(filteredParser); 
     // Consume/process the node for example: 
     JsonPointer fieldRelativePath = JsonPointer.compile("/test1"); 
     JsonNode valueNode = nextNode.at(fieldRelativePath); 
     if (!valueNode.isValueNode()) { 
      throw new IllegalStateException("Did not find value at " 
        + fieldRelativePath.toString() 
        + " after setting base to " + basePath.toString()); 
     } 
     System.out.println(valueNode.asText()); 
    } 
} 
संबंधित मुद्दे