การแปลงข้อมูล JSON เป็นวัตถุ Java


262

ฉันต้องการเข้าถึงคุณสมบัติจากสตริง JSON ภายในวิธีการกระทำของ Java ของฉัน myJsonString = object.getJson()สตริงสามารถใช้ได้โดยเพียงแค่บอกว่า ด้านล่างเป็นตัวอย่างของสิ่งที่สตริงสามารถมีลักษณะ:

{
    'title': 'ComputingandInformationsystems',
    'id': 1,
    'children': 'true',
    'groups': [{
        'title': 'LeveloneCIS',
        'id': 2,
        'children': 'true',
        'groups': [{
            'title': 'IntroToComputingandInternet',
            'id': 3,
            'children': 'false',
            'groups': []
        }]
    }]
}

ในสายนี้ทุกวัตถุ JSON มีอาร์เรย์ของวัตถุ JSON อื่น ๆ ความตั้งใจคือการแยกรายการของรหัสที่วัตถุที่กำหนดใด ๆ ที่มีคุณสมบัติกลุ่มที่มีวัตถุ JSON อื่น ๆ ฉันดู Gson ของ Google เป็นปลั๊กอิน JSON ที่มีศักยภาพ ทุกคนสามารถให้คำแนะนำในรูปแบบว่าฉันจะสร้าง Java จากสตริง JSON นี้ได้อย่างไร



นี่คือตัวอย่างthegeekyland.blogspot.com/2015/11/…
Arlind

คำตอบ:


329

ฉันดู Gson ของ Google เป็นปลั๊กอิน JSON ที่มีศักยภาพ ทุกคนสามารถให้คำแนะนำในรูปแบบว่าฉันจะสร้าง Java จากสตริง JSON นี้ได้อย่างไร

Google Gsonรองรับยาสามัญและถั่วที่ซ้อนกัน []ใน JSON หมายถึงอาร์เรย์และควรแมปกับคอลเลกชัน Java เช่นListหรือเพียงแค่อาร์เรย์ Java ธรรมดา กระบวนการ{}ใน JSON หมายถึงวัตถุและควรแมปกับ Java Mapหรือเพียงบางคลาส JavaBean

คุณมีอ็อบเจ็กต์ JSON ที่มีคุณสมบัติหลายอย่างซึ่งgroupsคุณสมบัตินี้แทนอาร์เรย์ของออบเจกต์ที่ซ้อนกันที่เป็นชนิดเดียวกัน สามารถแยกวิเคราะห์ด้วย Gson ด้วยวิธีต่อไปนี้:

package com.stackoverflow.q1688099;

import java.util.List;
import com.google.gson.Gson;

public class Test {

    public static void main(String... args) throws Exception {
        String json = 
            "{"
                + "'title': 'Computing and Information systems',"
                + "'id' : 1,"
                + "'children' : 'true',"
                + "'groups' : [{"
                    + "'title' : 'Level one CIS',"
                    + "'id' : 2,"
                    + "'children' : 'true',"
                    + "'groups' : [{"
                        + "'title' : 'Intro To Computing and Internet',"
                        + "'id' : 3,"
                        + "'children': 'false',"
                        + "'groups':[]"
                    + "}]" 
                + "}]"
            + "}";

        // Now do the magic.
        Data data = new Gson().fromJson(json, Data.class);

        // Show it.
        System.out.println(data);
    }

}

class Data {
    private String title;
    private Long id;
    private Boolean children;
    private List<Data> groups;

    public String getTitle() { return title; }
    public Long getId() { return id; }
    public Boolean getChildren() { return children; }
    public List<Data> getGroups() { return groups; }

    public void setTitle(String title) { this.title = title; }
    public void setId(Long id) { this.id = id; }
    public void setChildren(Boolean children) { this.children = children; }
    public void setGroups(List<Data> groups) { this.groups = groups; }
    
    public String toString() {
        return String.format("title:%s,id:%d,children:%s,groups:%s", title, id, children, groups);
    }
}

ค่อนข้างง่ายใช่มั้ย เพียงแค่มี JavaBean และการโทรที่Gson#fromJson()เหมาะสม

ดูสิ่งนี้ด้วย:


4
performant? คุณวัดจริงหรือไม่ ในขณะที่ GSON มีชุดคุณสมบัติที่เหมาะสมฉันคิดว่าประสิทธิภาพเป็นจุดอ่อน (ตาม [ cowtowncoder.com/blog/archives/2009/09/entry_326.html] ) ตามตัวอย่าง: ฉันคิดว่า GSON ไม่ต้องการตัวตั้งค่าและ ขึ้นอยู่กับสาขา ดังนั้นรหัสอาจจะง่ายขึ้นเล็กน้อย
StaxMan

3
ฉันใช้มันในแอพ Android มันไม่ใช่วิธีที่เร็วที่สุดที่เป็นไปได้ แต่มันง่ายพอที่จะตั้งโปรแกรมเพื่อแสดงให้เห็นถึงการขาดประสิทธิภาพสำหรับผู้ใช้จนถึงปัจจุบัน บางทีในแอปเวอร์ชันที่ใหม่กว่านั้นจะถูกลบออกเพื่อการแก้ปัญหาที่เร็วขึ้น
Janusz

1
ความเร็วของการเขียนถ้ามันเร็วพอมันเร็วพอ ฉันเพิ่งแสดงความคิดเห็นในการอ้างอิงถึงผลงานที่ดีที่คาดหวัง แจ็คสันฉลาดหลักแหลมในการจัดการคุณสมบัติจัดการกับรังซ้อนเลเยอร์ชื่อสามัญทั้งหมดดังนั้นจึงไม่ใช่สิ่งที่ความแตกต่างของความเร็วมาจาก การมีผู้ได้รับและผู้ตั้งค่าไม่ส่งผลกระทบต่อประสิทธิภาพการทำงานในลักษณะที่วัดได้ (สำหรับแพ็คเกจที่ฉันทราบ) ดังนั้นจึงสามารถมีได้อย่างแน่นอน
StaxMan

97
+1 สำหรับ "package com.stackoverflow.q1688099;" ด้วยเหตุผลบางอย่างมันทำให้ฉันหัวเราะหึๆ
GargantuChet

1
String สาธารณะ toString () {กลับ Gson ใหม่ (). toJson (นี้); // ใช้สิ่งนี้แทนที่จะเขียนตัวแปรแต่ละตัว}
Prakash

45

Bewaaaaare จาก Gson! มันยอดเยี่ยมมากยอดเยี่ยมมาก แต่ครั้งที่สองที่คุณต้องการทำสิ่งอื่นนอกเหนือจากวัตถุธรรมดาคุณอาจต้องเริ่มสร้างซีเรียลไลเซอร์ของคุณเอง (ซึ่งไม่ยากอย่างนั้น )

นอกจากนี้หากคุณมีอาร์เรย์ของวัตถุและคุณเลิกทำการ json บางส่วนลงในอาร์เรย์ของวัตถุนั้นประเภทที่แท้จริงคือ LOST! วัตถุทั้งหมดจะไม่ถูกคัดลอก! ใช้ XStream .. ซึ่งหากใช้ jsondriver และตั้งค่าที่เหมาะสมจะเข้ารหัสประเภทที่น่าเกลียดใน json จริงเพื่อที่คุณจะไม่เสียอะไรเลย ราคาขนาดเล็กที่ต้องจ่าย (น่าเกลียด json) สำหรับการทำให้เป็นอนุกรมที่แท้จริง

โปรดทราบว่าแจ็คสันแก้ไขปัญหาเหล่านี้และเร็วกว่า GSON


2
ฉันเขียนส้อมของ Gson ซึ่งแก้ไขปัญหาเหล่านี้ (และหลีกเลี่ยงการเพิ่มความคิดเห็นทั้งหมดของแจ็คสัน): github.com/winterstein/flexi-gson
Daniel Winterstein

26

น่าแปลกที่หน่วยประมวลผล JSON ที่เหมาะสมที่กล่าวถึงในตอนนี้คือ GSON

นี่คือตัวเลือกที่ดีกว่า:

  • Jackson ( Github ) - การเชื่อมโยงข้อมูลที่มีประสิทธิภาพ (JSON ไปยัง / จาก POJOs), สตรีมมิ่ง (เร็วเป็นพิเศษ), โมเดลทรี (สะดวกสำหรับการเข้าถึงแบบไม่พิมพ์)
  • Flex-JSON - การทำให้เป็นอนุกรมที่สามารถกำหนดค่าได้สูง

แก้ไข (ส.ค. / 2556):

อีกหนึ่งข้อที่ควรพิจารณา:

  • Genson - ฟังก์ชั่นคล้ายกับแจ็กสันมีวัตถุประสงค์เพื่อให้ง่ายต่อการกำหนดค่าโดยนักพัฒนา

15

หรือกับแจ็คสัน:

String json = "...
ObjectMapper m = new ObjectMapper();
Set<Product> products = m.readValue(json, new TypeReference<Set<Product>>() {});

สิ่งนี้จะทำให้เกิดข้อผิดพลาดที่ไม่สามารถทำการ deserialize อินสแตนซ์ของ java.util.HashSet ออกจากโทเค็น START_OBJECT ได้
Dipen Chawla

7

หากมีการเปลี่ยนแปลงใด ๆ คุณอยู่ในแอปพลิเคชันที่ใช้http://restfb.com/ อยู่แล้วคุณสามารถทำได้:

import com.restfb.json.JsonObject;

...

JsonObject json = new JsonObject(jsonString);
json.get("title");

เป็นต้น


วิธีแก้ปัญหาของคุณสั้นลงและเข้าใจง่ายขึ้นว่าทำไมรับเพียง 3 upvotes เท่านั้น มีอะไรผิดปกติหรือเปล่า?
Jeff

4

ง่ายต่อการใช้งานรหัสจาวาในการแปลงJSONObjectเป็นJava Object

Employee.java

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Generated;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

@JsonInclude(JsonInclude.Include.NON_NULL)
@Generated("org.jsonschema2pojo")
@JsonPropertyOrder({
"id",
"firstName",
"lastName"
})
public class Employee {

@JsonProperty("id")
private Integer id;
@JsonProperty("firstName")
private String firstName;
@JsonProperty("lastName")
private String lastName;
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();

/**
*
* @return
* The id
*/
@JsonProperty("id")
public Integer getId() {
return id;
}

/**
*
* @param id
* The id
*/
@JsonProperty("id")
public void setId(Integer id) {
this.id = id;
}

/**
*
* @return
* The firstName
*/
@JsonProperty("firstName")
public String getFirstName() {
return firstName;
}

/**
*
* @param firstName
* The firstName
*/
@JsonProperty("firstName")
public void setFirstName(String firstName) {
this.firstName = firstName;
}

/**
*
* @return
* The lastName
*/
@JsonProperty("lastName")
public String getLastName() {
return lastName;
}

/**
*
* @param lastName
* The lastName
*/
@JsonProperty("lastName")
public void setLastName(String lastName) {
this.lastName = lastName;
}

@JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}

@JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}

}

LoadFromJSON.java

import org.codehaus.jettison.json.JSONObject;

import com.fasterxml.jackson.databind.ObjectMapper;

public class LoadFromJSON {

    public static void main(String args[]) throws Exception {
        JSONObject json = new JSONObject();
        json.put("id", 2);
        json.put("firstName", "hello");
        json.put("lastName", "world");

        byte[] jsonData = json.toString().getBytes();

        ObjectMapper mapper = new ObjectMapper();
        Employee employee = mapper.readValue(jsonData, Employee.class);

        System.out.print(employee.getLastName());

    }
}

จะเข้าถึงคุณสมบัติ json เหล่านี้ใน JSP ได้อย่างไร
Zoran777

หากคุณไม่ต้องการใช้ในหน้า JSP รหัสก็ยังเหมือนเดิม คลาส Employee.java จะเหมือนกันทุกประการ แต่รหัสที่เขียนใน LoadFromJSON.java จะถูกคัดลอกในหน้า jsp พร้อมกับการนำเข้าที่ถูกต้องของทุกคลาส พักผ่อนไม่มีการเปลี่ยนแปลงเลย
ราหุลเรนนะ


3

หากคุณใช้แผนที่พิเศษใด ๆ ที่มีคีย์หรือค่าเช่นเดียวกับแผนที่พิเศษคุณจะพบว่ามันไม่ได้ถูกพิจารณาจากการนำ google ไปใช้


2

มีอะไรผิดปกติกับสิ่งมาตรฐานหรือไม่

JSONObject jsonObject = new JSONObject(someJsonString);
JSONArray jsonArray = jsonObject.getJSONArray("someJsonArray");
String value = jsonArray.optJSONObject(i).getString("someJsonValue");

มันช้ามาก: github.com/fabienrenaud/java-json-benchmarkเมื่อเร็ว ๆ นี้ที่งานฉันเพิ่มประสิทธิภาพเป็นสองเท่า (การใช้งานซีพียูลดลงครึ่งหนึ่งลดเวลาในการตอบสนองต่อการหยุดชะงัก) ของเซิร์ฟเวอร์ Prod ของเราโดยเปลี่ยนการเรียกใช้ org / json ทั้งหมด / deserialization ใช้แจ็คสัน
fabien

0

ลองทำสิ่งที่เป็นประโยชน์:

https://github.com/RichardHightower/boon

มันเร็วมาก

https://github.com/RichardHightower/json-parsers-benchmark

อย่าใช้คำพูดของฉันมัน ... ตรวจสอบมาตรฐาน gatling

https://github.com/gatling/json-parsers-benchmark

(มากถึง 4x เป็นกรณีและออกจากการทดสอบ 100 ครั้งนอกจากนี้ยังมีโหมดการซ้อนทับดัชนีที่เร็วยิ่งขึ้นมันยังเด็ก แต่มีผู้ใช้บางส่วนแล้ว)

มันสามารถแยก JSON ไปที่แผนที่และรายการเร็วกว่า lib อื่น ๆ สามารถแยกไปยัง JSON DOM และที่ไม่มีโหมดการซ้อนทับดัชนี ด้วยโหมด Boon Index Overlay มันจะเร็วยิ่งขึ้น

นอกจากนี้ยังมีโหมด JSON lax ที่รวดเร็วมากและโหมด parser PLIST :) (และมีหน่วยความจำต่ำมากโดยตรงจากโหมดไบต์ด้วยการเข้ารหัส UTF-8 ทันที)

นอกจากนี้ยังมีโหมด JSON เป็น JavaBean ที่เร็วที่สุดด้วย

มันเป็นเรื่องใหม่ แต่ถ้าความเร็วและ API แบบง่ายคือสิ่งที่คุณกำลังมองหาฉันไม่คิดว่าจะมี API ที่เร็วขึ้นหรือน้อยกว่า


คุณสามารถให้ลิงค์สำหรับเอกสารล่าสุดสำหรับรุ่นล่าสุดได้หรือไม่ ณ วันนี้ฉันพบ 0.4 แต่ไม่สามารถค้นหาลิงก์ doc ที่ตรงกันหรือแบบฝึกหัดสำหรับรุ่นนั้นได้อย่างง่ายดาย ขอบคุณ
Bizmarck

นี่คือบทช่วยสอนgithub.com/RichardHightower/boon/wiki/Boon-JSON-in-five-minutes Boon อยู่ใน repo maven สาธารณะ อยู่ที่ 0.27 หรือมากกว่านั้น
RickHigh

richardhightower.github.io/site/releasesมี 0.4 ดังนั้นฉันคิดว่ามันเป็นเวอร์ชั่นล่าสุด ฉันได้ตรวจสอบ Boon สำหรับโครงการที่ทำงานแล้วมีคำอธิบายประกอบที่เทียบเท่ากับ @JsonIgnore ของ Jackson หรือไม่
Bizmarck

ประโยชน์อยู่ที่ส่วนล่างของประสิทธิภาพ ser / deserialization: github.com/fabienrenaud/java-json-benchmarkเลือกแจ็คสันหรือ dsljson เพื่อประสิทธิภาพ @ RickHigh: ฉันไม่สามารถเปิดปัญหาใน GitHub ของคุณฉันยินดีที่จะปรับปรุงมาตรฐานของฉันหรือแก้ไขการตีความถ้ามีอะไรผิดปกติ / ที่ฉันพลาดเกี่ยวกับมัน
fabien

0

ขึ้นอยู่กับรูปแบบ JSON อินพุต (สตริง / ไฟล์) สร้าง jSONString ตัวอย่างคลาสอ็อบเจ็กต์ข้อความที่สอดคล้องกับ JSON สามารถรับได้ดังนี้:

ข้อความ msgFromJSON = ObjectMapper ใหม่ (). readValue (jSONString, Message.class);


0

วิธีที่ง่ายที่สุดคือคุณสามารถใช้วิธี softconvertvalue ซึ่งเป็นวิธีที่กำหนดเองซึ่งคุณสามารถแปลง jsonData เป็นคลาส Dto เฉพาะของคุณ

Dto response = softConvertValue(jsonData, Dto.class);


public static <T> T softConvertValue(Object fromValue, Class<T> toValueType) 
{
    ObjectMapper objMapper = new ObjectMapper();
    return objMapper
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        .convertValue(fromValue, toValueType);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.