Bir JSON dizesini Jackson JsonNode ayrıştırmak nasıl?


231

Çok basit olmalı, ama bir saat #embarrasing denedikten sonra bulamıyorum.

Ben örneğin, JSON dizesi almak gerekir {"k1":v1,"k2":v2}, bir şekilde çözümlenir JsonNode.

JsonFactory factory = new JsonFactory();
JsonParser jp = factory.createJsonParser("{\"k1\":\"v1\"}");
JsonNode actualObj = jp.readValueAsTree();

verir

java.lang.IllegalStateException: No ObjectCodec defined for the parser, can not deserialize JSON into JsonNode tree


54
#embarrasing-- Hayır. Basit şeyler basit değilse, API tasarımcısı başarısız olmuştur, siz değil.
jameshfisher

@ StaxMan'ın koddaki cevabı: JsonFactory factory = new MappingJsonFactory ();
Juan Rojas

Yanıtlar:


371

Richards'ın cevabında küçük bir değişiklik var, ancak readTreebir dizeyi alabilir, böylece basitleştirebilirsiniz:

ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree("{\"k1\":\"v1\"}");

44
ObjectNodeJsonNodemapper.valueToTree("{\"k1\":\"v1\"}")
Matthew Herbst

5
@MatthewHerbst 2.5.1 sürümünde bu, JSON olarak ayrıştırmak yerine "{\" k1 \ ": \" v1 \ "}" dizesiyle yeni bir metin düğümü oluşturur.
minexew

69

Bir kullanmanız gerekir ObjectMapper:

ObjectMapper mapper = new ObjectMapper();
JsonFactory factory = mapper.getJsonFactory(); // since 2.1 use mapper.getFactory() instead
JsonParser jp = factory.createJsonParser("{\"k1\":\"v1\"}");
JsonNode actualObj = mapper.readTree(jp);

Ayrıştırıcı oluşturma hakkında daha fazla belge burada bulunabilir .


JsonNode almak, biraz değiştirmek ve sonra mapper.readValue (düğüm, sınıf) çağırmak mümkün mü; ve bir ders çıkarır mısın?
portforwardpodcast

1
Evet. Bunun için bir takma ad bile var mapper.treeToValue(). Ama readValue()aynı zamanda çalışıyor.
StaxMan

Bağlantı kopmuş gibi görünüyor
manuna

28

Üçüncü bir varyant:

ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readValue("{\"k1\":\"v1\"}", JsonNode.class);

JsonNode.class uygulamasından geçmek sizi buraya ne getirdi?
David

3
@David: Hiçbir şey, bu yüzden slashnick'in varyantı sadece bir istiyorsanız daha iyi JsonNode. Ancak, genellikle bir istemezsiniz JsonNode, bu yüzden Jackson'a ne tür bir değer istediğinizi nasıl söylemek istediğinizi göstermek istedim.
qerub

Benim için, JsonNodeJackson'ın bunu başka bir şey olarak serileştirmesini önlemek için geçmek gerekliydi - ki bu başarısız olurdu.
Cory Klein

5

Richard'ın cevabı doğru. Alternatif olarak, nerede bulacağını bilen bir MappingJsonFactory(in org.codehaus.jackson.map) de oluşturabilirsiniz ObjectMapper. Düzenli çünkü var hata oldu JsonFactory(den corepaketine) için hiçbir bağımlılığı ObjectMapper(içindedir mapperpaketin).

Ancak genellikle sadece veya diğer düşük seviyeli bileşenleri kullanır ObjectMapperve endişelenmezsiniz JsonParser- sadece akışın parçalarını veri bağlamak veya düşük seviyeli işlem yapmak istiyorsanız bunlara ihtiyacınız olacaktır.


3
import com.github.fge.jackson.JsonLoader;
JsonLoader.fromString("{\"k1\":\"v1\"}")
== JsonNode = {"k1":"v1"}

0

Eski soruya yeni yaklaşım. Java 9+ ile çalışan bir çözüm

ObjectNode agencyNode = new ObjectMapper().valueToTree(Map.of("key", "value"));

karmaşık nesneler için daha okunabilir ve bakımı daha kolaydır. Ej

Map<String, Object> agencyMap = Map.of(
        "name", "Agencia Prueba",
        "phone1", "1198788373",
        "address", "Larrea 45 e/ calligaris y paris",
        "number", 267,
        "enable", true,
        "location", Map.of("id", 54),
        "responsible", Set.of(Map.of("id", 405)),
        "sellers", List.of(Map.of("id", 605))
);
ObjectNode agencyNode = new ObjectMapper().valueToTree(agencyMap);
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.