แปลง JsonNode เป็น POJO


143

นี้อาจดูเหมือนผิดปกติเล็ก ๆ น้อย ๆ แต่ฉันกำลังมองหาวิธีที่มีประสิทธิภาพในการแปลง / แมปเป็นJsonNodePOJO

ฉันเก็บข้อมูลโมเดลของฉันไว้ในไฟล์ json และฉันต้องสนับสนุนโมเดลของฉันสองสามรุ่น

สิ่งที่ฉันทำคือโหลดไฟล์ json ในหน่วยความจำใน JsonNode ใช้กลยุทธ์การกำหนดรุ่นสองสามอย่างเพื่อให้ตรงกับรุ่นล่าสุดของรุ่นของฉัน

    ObjectMapper mapper = new ObjectMapper();
    BufferedReader fileReader = new BufferedReader(new FileReader(projPath));

    JsonNode rootNode = mapper.readTree(fileReader);

    //Upgrade our file in memory
    applyVersioningStrategy(rootNode);

    ProjectModel project = mapJsonNodeToProject(rootNode);

หากไม่มีวิธีที่เร็วกว่าในการทำเช่นนั้นฉันอาจจะลงเอยด้วยตนเองเพียงแค่นำJsonNodesโมเดลของฉันไปใช้ด้วยตนเอง

คำตอบ:


264

ใน Jackson 2.4 คุณสามารถแปลงดังนี้:

MyClass newJsonNode = jsonObjectMapper.treeToValue(someJsonNode, MyClass.class);

ที่เป็นแจ็คสันjsonObjectMapperObjectMapper


ในรุ่นเก่าของแจ็คสันมันจะเป็น

MyClass newJsonNode = jsonObjectMapper.readValue(someJsonNode, MyClass.class);

19
น่าเสียดายที่ไม่มีตัวแปร treeToValue (TreeNode n, TypeReference <T> type) เหมือนที่อ่านไว้สำหรับ readValue () ข่าวร้ายสำหรับทุกคนที่เกี่ยวข้องกับประเภทที่ซับซ้อนยิ่งขึ้นกับยาชื่อสามัญ :(
Espinosa

13
@Espinosa Per jackson-databind # 1294คุณจะต้องการอะไร (น่าเสียดายยิ่งกว่า verbose)jsonObjectMapper.readValue(jsonObjectMapper.treeAsTokens(someJsonNode), someTypeReference)
M. Justin

สำหรับรุ่นเก่าใช้:objectMapper.treeToValue(jsonNode, MyClass.class)
amod

2
นอกจากนี้คุณยังสามารถใช้วิธีนี้ใน p.codec.treeToValueStdDeserializer:
galcyurio

@icedtrees jsonObjectMapper เป็นตัวอย่างของ JsonObjectMapper หรือเพียงแค่ ObjectMapper
KNDheeraj

8

สิ่งนี้ควรทำเคล็ดลับ:

mapper.readValue(fileReader, MyClass.class);

ฉันควรจะพูดเพราะฉันใช้สิ่งนั้นกับ a Stringไม่ใช่BufferedReaderแต่ควรใช้งานได้

นี่คือรหัสของฉัน:

String inputString = // I grab my string here
MySessionClass sessionObject;
try {
    ObjectMapper objectMapper = new ObjectMapper();
    sessionObject = objectMapper.readValue(inputString, MySessionClass.class);

นี่คือเอกสารอย่างเป็นทางการสำหรับการโทร: http://jackson.codehaus.org/1.7.9/javadoc/org/codehaus/jackson/map/ObjectMapper.html#readValue(java.lang.String, java.lang.Class)

คุณยังสามารถกำหนดตัว deserializer แบบกำหนดเองเมื่อคุณสร้างอินสแตนซ์ObjectMapper: http://wiki.fasterxml.com/JacksonHowToCustomDeserializers

แก้ไข: ฉันเพิ่งจำอย่างอื่น หากวัตถุของคุณเข้ามามีคุณสมบัติมากกว่าที่POJOมีและคุณเพียงแค่ต้องการละเว้นสิ่งพิเศษที่คุณจะต้องตั้งค่านี้:

    objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

หรือคุณจะได้รับข้อผิดพลาดที่ไม่สามารถหาสถานที่ตั้งได้


ฉันจะใช้ CustomDeserializers มันจะช่วยให้ฉันปวดหัวมาก! ฉันจะสามารถใช้กลยุทธ์การกำหนดรุ่นของฉันด้วยการปรับเปลี่ยนเล็กน้อย ขอบคุณ!
Alexandre

5
ไวยากรณ์อยู่ในขณะนี้: com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper (); mapper.disable (com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
llambda

จุดที่ดี @llambda! ฉันไม่ได้สัมผัส ObjectMapper ตั้งแต่รุ่น 1.7.9 ดูเหมือนว่าคำตอบของฉันล้าสมัยไปแล้วสองสามเวอร์ชัน ตรวจสอบรุ่นแจ็คสันที่คุณใช้อยู่อย่างแน่นอน
Eric Barr

@EricBarr ฉันใช้ Jackson v1.9.11 และไวยากรณ์ในคำตอบของคุณนั้นถูกต้องสำหรับรุ่นนั้น บางทีพวกเขาพยายามที่จะเปลี่ยนแปลงสิ่งต่าง ๆ และคืนกลับมาอีกครั้งในเวอร์ชันที่ใหม่กว่า
Ivaylo Slavov

5

หากคุณใช้ org.codehaus.jackson สิ่งนี้เป็นไปได้ตั้งแต่ 1.6 คุณสามารถแปลง JsonNode เป็น POJO ด้วยObjectMapper#readValue: http://jackson.codehaus.org/1.9.4/javadoc/org/codehaus/jackson/map/ObjectMapper.html#readValue(org.codehaus.jackson.JsonNode , java lang.Class)


    ObjectMapper mapper = new ObjectMapper();
    JsonParser jsonParser = mapper.getJsonFactory().createJsonParser("{\"foo\":\"bar\"}");
    JsonNode tree = jsonParser.readValueAsTree();
    // Do stuff to the tree
    mapper.readValue(tree, Foo.class);

5
วิธีการนี้ดูเหมือนว่าจะหายไปใน 2.4.4
Kevin Wittek

1
ดูคำตอบของ icedtrees ด้านล่างสำหรับวิธีแก้ปัญหารุ่นที่ 2
Tim Büthe


3
String jsonInput = "{ \"hi\": \"Assume this is the JSON\"} ";
com.fasterxml.jackson.databind.ObjectMapper mapper =
    new com.fasterxml.jackson.databind.ObjectMapper();
MyClass myObject = objectMapper.readValue(jsonInput, MyClass.class);

หากอินพุต JSON ของคุณมีคุณสมบัติมากกว่า POJO ของคุณและคุณเพียงต้องการละเว้นสิ่งพิเศษใน Jackson 2.4 คุณสามารถกำหนดค่า ObjectMapper ของคุณได้ดังต่อไปนี้ ไวยากรณ์นี้แตกต่างจาก Jackson รุ่นเก่า (ถ้าคุณใช้ไวยากรณ์ผิดมันจะไม่ทำอะไรเลยในใจ)

mapper.disable(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNK‌​NOWN_PROPERTIES);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.