JSON แยกวิเคราะห์โดยใช้ Gson สำหรับ Java


154

ฉันต้องการที่จะแยกข้อมูลจาก JSON Stringซึ่งเป็นประเภท ฉันใช้Google Gson

ฉันมี:

jsonLine = "
{
 "data": {
  "translations": [
   {
    "translatedText": "Hello world"
   }
  ]
 }
}
";

และชั้นเรียนของฉันคือ:

public class JsonParsing{

   public void parse(String jsonLine) {

      // there I would like to get String "Hello world"

   }

}

ที่คล้ายกัน: stackoverflow.com/questions/4110664/…
Vadzim

คำตอบ:


241

นี่เป็นรหัสง่ายๆที่จะทำฉันหลีกเลี่ยงการตรวจสอบทั้งหมด แต่นี่เป็นแนวคิดหลัก

 public String parse(String jsonLine) {
    JsonElement jelement = new JsonParser().parse(jsonLine);
    JsonObject  jobject = jelement.getAsJsonObject();
    jobject = jobject.getAsJsonObject("data");
    JsonArray jarray = jobject.getAsJsonArray("translations");
    jobject = jarray.get(0).getAsJsonObject();
    String result = jobject.get("translatedText").getAsString();
    return result;
}

เพื่อให้ใช้งานทั่วไปได้มากขึ้น - คุณจะพบว่าjavadocs ของ Gsonค่อนข้างชัดเจนและเป็นประโยชน์


1
JsonObject ขยาย JsonElement ดังนั้นทั้งคู่
MByD

บรรทัดแรกพ่นไม่สามารถ instantiate ประเภท JsonParser กับรุ่น gson-2.2.4.jar
อาร์กิวเมนต์ที่ผิดกฎหมาย

3
String result = jobject.get ("translateText"). toString (); ผลลัพธ์นี้จะรวมเครื่องหมายคำพูดคู่ String result = jobject.get ("translateText"). getAsString (); ไม่รวมคำพูด
user1165560

ฉันเป็นคนเดียวที่คิดว่า Gson เข้าใจเรื่อง 98% ของเวลา? JSONObject ง่าย ๆ จะทำ แต่เราทุกคนเกลียดการลอง / จับมากขนาดนั้น?
เคล็ดลับ

ฉันต้องใช้คลาส parser แต่ฉันได้รับ MalformedJsonException ดังนั้นฉันต้องสามารถใช้ SetLeinient กับ JsonParser ได้ อย่างไร?
Mason Wang

111

ในแอปพลิเคชัน gson แรกของฉันฉันหลีกเลี่ยงการใช้คลาสเพิ่มเติมเพื่อตรวจจับค่าเป็นหลักเพราะฉันใช้ json สำหรับเรื่องการกำหนดค่า

แม้จะไม่มีข้อมูล (แม้แต่หน้า gson) นั่นคือสิ่งที่ฉันพบและใช้:

เริ่มจาก

Map jsonJavaRootObject = new Gson().fromJson("{/*whatever your mega complex object*/}", Map.class)

แต่ละครั้งที่ gson เห็น {} จะสร้างแผนที่ (ที่จริงแล้วคือ gson StringMap)

แต่ละครั้งที่ gson เห็น '' มันจะสร้างสตริง

แต่ละครั้งที่ gson เห็นตัวเลขมันจะสร้าง Double

แต่ละครั้งที่ gson เห็น [] มันจะสร้าง ArrayList

คุณสามารถใช้ข้อเท็จจริงนี้ (รวมกัน) เพื่อประโยชน์ของคุณ

ในที่สุดนี่คือรหัสที่ทำให้สิ่งนั้น

        Map<String, Object> javaRootMapObject = new Gson().fromJson(jsonLine, Map.class);

    System.out.println(
        (
            (Map)
            (
                (List)
                (
                    (Map)
                    (
                        javaRootMapObject.get("data")
                    )
                 ).get("translations")
            ).get(0)
        ).get("translatedText")
    );

20

สิ่งที่ง่ายที่สุดคือการสร้างลำดับชั้นของวัตถุที่ตรงกันเช่น:

public class Wrapper {
   public Data data;
}
static class Data {
   public Translation[] translations;
}
static class Translation {
   public String translatedText;
}

จากนั้นผูกโดยใช้ GSON สำรวจลำดับชั้นของวัตถุผ่านช่อง การเพิ่ม getters และ setters นั้นไม่มีประโยชน์สำหรับคอนเทนเนอร์ข้อมูลพื้นฐาน

ดังนั้นสิ่งที่ชอบ:

Wrapper value = GSON.fromJSON(jsonString, Wrapper.class);
String text = value.data.translations[0].translatedText;

2
ดังนั้นโครงสร้างวัตถุของคุณไม่ตรงกับ JSON
StaxMan

14

คุณสามารถสร้างคลาส Java ที่สอดคล้องกันสำหรับวัตถุ json จำนวนเต็มค่าสตริงสามารถถูกแมปตามที่เป็นอยู่ Json สามารถแยกวิเคราะห์ได้เช่นนี้ -

Gson gson = new GsonBuilder().create(); 
Response r = gson.fromJson(jsonString, Response.class);

นี่คือตัวอย่าง - http://rowsandcolumns.blogspot.com/2013/02/url-encode-http-get-solr-request-and.html


8

คุณสามารถใช้คลาสแยกเพื่อแสดงวัตถุ JSON และใช้@SerializedNameคำอธิบายประกอบเพื่อระบุชื่อฟิลด์ที่จะคว้าสำหรับสมาชิกข้อมูลแต่ละราย:

public class Response {

   @SerializedName("data")
   private Data data;

   private static class Data {
      @SerializedName("translations")
      public Translation[] translations;
   }

   private static class Translation {
      @SerializedName("translatedText")
      public String translatedText;
   }

   public String getTranslatedText() {
      return data.translations[0].translatedText;
   }
}

จากนั้นคุณสามารถแยกวิเคราะห์ในวิธีการแยกวิเคราะห์ () ของคุณโดยใช้Gsonวัตถุ:

Gson gson = new Gson();
Response response = gson.fromJson(jsonLine, Response.class);

System.out.println("Translated text: " + response.getTranslatedText());

ด้วยวิธีนี้คุณสามารถใช้Responseคลาสนี้เพื่อเพิ่มฟิลด์เพิ่มเติมอื่น ๆ เพื่อรับสมาชิกข้อมูลอื่น ๆ ที่คุณอาจต้องการแยกออกจาก JSON - ในกรณีที่คุณต้องการเปลี่ยนแปลงเพื่อรับผลลัพธ์พูดการแปลหลายครั้งในการโทรครั้งเดียว หรือเพื่อรับสตริงเพิ่มเติมสำหรับภาษาต้นฉบับที่ตรวจพบ


7

วิธีหนึ่งจะสร้าง JsonObject และวนซ้ำผ่านพารามิเตอร์ ตัวอย่างเช่น

JsonObject jobj = new Gson().fromJson(jsonString, JsonObject.class);

จากนั้นคุณสามารถแยกค่า bean เช่น:

String fieldValue = jobj.get(fieldName).getAsString();
boolean fieldValue = jobj.get(fieldName).getAsBoolean();
int fieldValue = jobj.get(fieldName).getAsInt();

หวังว่านี่จะช่วยได้


5

การใช้ Gson เพื่อแก้ไข
ฉันจะสร้างคลาสสำหรับพารามิเตอร์แต่ละตัวใน json String หรือคุณสามารถสร้างคลาสหลักหนึ่งคลาสที่เรียกว่า "Data" จากนั้นสร้างคลาสภายในขึ้นมาในทำนองเดียวกัน ฉันสร้างคลาสแยกต่างหากเพื่อความชัดเจน

ชั้นเรียนมีดังนี้

  • ข้อมูล
  • การแปล
  • TranslatedText

ในคลาส JsonParsing วิธีการ "แจง" เราเรียกgson.fromJson(jsonLine, Data.class)ซึ่งจะแปลงสตริงในวัตถุ java โดยใช้การสะท้อน

เมื่อเราเข้าถึงวัตถุ "ข้อมูล" เราสามารถเข้าถึงพารามิเตอร์แต่ละรายการได้

ไม่ได้รับโอกาสในการทดสอบรหัสนี้ในขณะที่ฉันไม่อยู่ที่เครื่อง dev แต่สิ่งนี้น่าจะช่วยได้

ตัวอย่างและบทความดีๆ
http://albertattard.blogspot.com/2009/06/practical-example-of-gson.html
http://sites.google.com/site/gson/gson-user-guide

รหัส

public class JsonParsing{

       public void parse(String jsonLine) {

           Gson gson = new GsonBuilder().create();
           Data data = gson.fromJson(jsonLine, Data.class);

           Translations translations = data.getTranslation();
           TranslatedText[] arrayTranslatedText = translations.getArrayTranslatedText(); //this returns an array, based on json string

           for(TranslatedText translatedText:arrayTranslatedText )
           {
                  System.out.println(translatedText.getArrayTranslatedText());
           }
       }

    }


    public class Data{
           private  Translations translations;
          public Translations getTranslation()
          {
             return translations;
          }

          public void setTranslation(Translations translations)
           {
                  this.translations = translations;
           }
    }

    public class Translations
    {
        private  TranslatedText[] translatedText;
         public TranslatedText[] getArrayTranslatedText()
         {
             return translatedText;
         }

           public void setTranslatedText(TranslatedText[] translatedText)
           {
                  this.translatedText= translatedText;
           }
    }

    public class TranslatedText
    {
        private String translatedText;
        public String getTranslatedText()
        {
           return translatedText;
        }

        public void setTranslatedText(String translatedText)
        {
           this.translatedText = translatedText;
        }
    }

คุณไม่ต้องการเซ็ตอัพในคลาสผู้ช่วยเหรอ? ไม่มีสิ่งใดสามารถตั้งค่าได้private String translatedTextโดยไม่ละเมิดการควบคุมการเข้าถึงดังนั้นจึงไม่มีวิธีใดที่fromJSONสามารถตั้งค่าไว้ใน JVMs ที่ไม่ได้เลือกใช้การเหยียบย่ำการสะท้อนการกระทืบทั้งหมดผ่านการควบคุมการเข้าถึง
Mike Samuel

@ Mike Samuel ยิงสมบูรณ์ลืมเกี่ยวกับ Setters
kensen john

3
    JsonParser parser = new JsonParser();
    JsonObject jo = (JsonObject) parser.parse(data);
    JsonElement je = jo.get("some_array");

    //Parsing back the string as Array
    JsonArray ja = (JsonArray) parser.parse(o.get("some_array").getAsString());
    for (JsonElement jo : ja) {
    JsonObject j = (JsonObject) jo;
        // Your Code, Access json elements as j.get("some_element")
    }

ตัวอย่างง่ายๆในการวิเคราะห์ JSON แบบนี้

{"some_array": "[\" some_element \ ": 1, \" some_more_element \ ": 2]", "some_other_element": 3}


2

ขั้นแรกสร้าง Getter และ Setter โดยใช้การแยกวิเคราะห์ไซต์ด้านล่าง

http://www.jsonschema2pojo.org/

ตอนนี้ใช้ Gson

GettetSetterClass object=new Gson().fromjson(jsonLine,GettetSetterClass.class);

ตอนนี้ใช้วัตถุเพื่อรับค่าเช่นข้อมูล translationText


2

คุณสามารถใช้แบบสอบถาม JsonPath เพื่อแยกค่า และด้วยJsonSurferซึ่งได้รับการสนับสนุนจาก Gson ปัญหาของคุณสามารถแก้ไขได้ด้วยเพียงแค่สองบรรทัดของโค้ด!

    JsonSurfer jsonSurfer = JsonSurfer.gson();
    String result = jsonSurfer.collectOne(jsonLine, String.class, "$.data.translations[0].translatedText");

1

รหัสหนึ่งบรรทัด:

System.out.println(new Gson().fromJson(jsonLine,JsonObject.class).getAsJsonObject().get("data").getAsJsonObject().get("translations").getAsJsonArray().get(0).getAsJsonObject().get("translatedText").getAsString());
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.