Jackson, JsonNode'u döküm yapmadan ArrayNode'a nasıl dönüştürebilir?


116

JSON kitaplığımı org.json'dan Jackson'a değiştiriyorum ve aşağıdaki kodu taşımak istiyorum:

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

Şimdi Jackson'da şunlara sahibim:

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

Ancak oradaki oyuncu kadrosunu sevmiyorum, bir olasılık var mı? ClassCastException mı? Bir yöntem eşdeğer var mı getJSONArrayiçinde org.jsonolma ihtimaline karşı uygun hata kaldırmaz, böylece bir dizi değil?


Maalesef veriler alan adlarını sabitlemediğinden tam eşlemeyi kullanamıyorum.
Konrad Höffner

1
Alan adları sınırlı bir kümeden geliyorsa, hepsini içeren bir sınıf tanımlamak FAIL_ON_UNKNOWN_PROPERTIESve kullanılmayan alanlarda döndürülen null değerleri almak için seriyi kaldırma özelliğini kullanmak isteyebilirsiniz. Ancak bu, elbette yalnızca alan adı grubu nispeten sınırlıysa bir seçenektir.
fvu

Hm, bu çözümün benim durumuma en iyi uymadığını düşünüyorum, ancak önceden bilinen sınırlı bir setle ilgili bir sorun yaşarsam diye hatırlayacağım!
Konrad Höffner

Yanıtlar:


247

Evet, Jackson manuel ayrıştırıcı tasarımı diğer kitaplıklardan oldukça farklıdır. Özellikle, JsonNodediğer API'lerden gelen dizi düğümleriyle tipik olarak ilişkilendireceğiniz işlevlerin çoğuna sahip olduğunu fark edeceksiniz . Bu nedenle, ArrayNodekullanmak için bir yayın yapmanıza gerek yoktur . İşte bir örnek:

JSON:

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

Kod:

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);
    }
}

Çıktı:

"Bir"
"İki"
"Üç"

isArrayYinelemeden önce düğümün aslında bir dizi olduğunu doğrulamak için kullanımına dikkat edin. Veri yapınızdan kesinlikle eminseniz kontrol gerekli değildir, ancak ihtiyacınız olması halinde kullanılabilir (ve bu, diğer JSON kitaplıklarının çoğundan farklı değildir).


2
Bana saatler kazandırdın. Teşekkürler!
Igor Morais

"(Son JsonNode objNode: arrNode)" satırında neden "final" kullanıldığını öğrenebilir miyim?
Anthony Vinay

5

Java 8'de bunu şu şekilde yapabilirsiniz:

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

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

1

Org.json'da getJSONArray'e eşdeğer bir yöntem var mı, böylece bir dizi olmaması durumunda uygun hata işlemeye sahip olabilir miyim?

Girişinize bağlıdır; ör. URL’den aldığınız şeyler. "Veri kümeleri" özniteliğinin değeri düz bir dizi yerine ilişkilendirilebilir bir diziyse, birClassCastException .

Ancak eski sürümünüzün doğruluğu da girdiye bağlıdır. Yeni sürümünüzün bir ClassCastExceptionatması durumunda, eski sürüm atacaktır JSONException. Referans: http://www.json.org/javadoc/org/json/JSONObject.html#getJSONArray(java.lang.String)


Ah tamam, böylece ClassCastException'ı yakalayabileyim, teşekkürler! Benim zevkime göre, belirli bir JsonException'a sahip olmaktan biraz daha az zarif ama mümkün değilse, aksi halde bu yine de iyi.
Konrad Höffner

0

Günün sonunda, ArrayNode'daki verileri yineleyerek tüketmek istediğinizi varsayıyorum. Bunun için:

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

veya akışlar ve lambda işlevleriyle ilgileniyorsanız:

import com.google.common.collect.Streams;
Streams.stream(datasets.withArray("datasets").elements())
    .forEach( item -> System.out.print(item.toString()) )
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.