Analiza JSON przy użyciu Gson for Java

154

Chciałbym przeanalizować dane z JSON, które są typu String. Używam Google Gson .

Mam:

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

a moja klasa to:

public class JsonParsing{

   public void parse(String jsonLine) {

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

   }

}
Martynas
źródło

Odpowiedzi:

241

To prosty kod, uniknąłem wszelkich kontroli, ale to jest główna idea.

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

Aby uczynić użycie bardziej ogólnym - przekonasz się, że javadoc firmy Gson są całkiem jasne i pomocne.

MByD
źródło
1
JsonObject rozszerza JsonElement, więc jest jednym i drugim.
MByD
pierwsza linia zgłasza nie może utworzyć wystąpienia typu JsonParser w wersji gson-2.2.4.jar
Illegal Argument
3
Wynik ciągu = jobject.get ("przetłumaczony tekst"). ToString (); Te wyniki będą zawierać podwójne cudzysłowy. Wynik ciągu = jobject.get ("przetłumaczony tekst"). GetAsString (); nie zawiera cudzysłowów.
user1165560
Czy ja jestem jedyną osobą, która uważa, że ​​Gson zbytnio komplikuje sprawę w 98% przypadków? Wystarczyłby prosty obiekt JSONObject, ale wszyscy nienawidzimy tak bardzo próbować / łapać?
tricknology
Muszę użyć klasy parsera, jednak otrzymuję MalformedJsonException, więc muszę mieć możliwość wykonania SetLeinient z JsonParser. W jaki sposób?
Mason Wang
111

W mojej pierwszej aplikacji gson unikałem używania dodatkowych klas do przechwytywania wartości, głównie dlatego, że używam json do spraw konfiguracyjnych

mimo braku informacji (choćby strony gson) to właśnie znalazłem i wykorzystałem:

zaczynając od

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

Za każdym razem, gdy gson widzi {}, tworzy Mapę (w rzeczywistości StringMap gson)

Za każdym razem, gdy gson widzi znak „”, tworzy ciąg

Za każdym razem, gdy gson widzi liczbę, tworzy Double

Za każdym razem, gdy gson widzi [], tworzy ArrayList

Możesz wykorzystać te fakty (łącznie) na swoją korzyść

Wreszcie to jest kod, który tworzy tę rzecz

        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")
    );
Jorge Sanchez
źródło
20

Zwykle najprostszą rzeczą jest utworzenie pasującej hierarchii obiektów, na przykład:

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

a następnie powiąż przy użyciu GSON, przeglądaj hierarchię obiektów za pomocą pól. Dodawanie metod pobierających i ustawiających jest bezcelowe w przypadku podstawowych kontenerów danych.

Więc coś takiego:

Wrapper value = GSON.fromJSON(jsonString, Wrapper.class);
String text = value.data.translations[0].translatedText;
StaxMan
źródło
2
Wtedy struktura obiektu NIE pasuje do formatu JSON.
StaxMan
8

Możesz użyć oddzielnej klasy do reprezentowania obiektu JSON i użyć @SerializedNameadnotacji, aby określić nazwę pola do pobrania dla każdego członka danych:

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

Następnie możesz wykonać parsowanie w metodzie parse () za pomocą Gsonobiektu:

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

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

Dzięki takiemu podejściu możesz ponownie użyć Responseklasy, aby dodać inne dodatkowe pola w celu pobrania innych członków danych, których możesz chcieć wyodrębnić z JSON - na wypadek, gdybyś chciał wprowadzić zmiany, aby uzyskać wyniki dla, powiedzmy, wielu tłumaczeń w jednym wywołaniu, lub uzyskać dodatkowy ciąg znaków dla wykrytego języka źródłowego.

rmtheis
źródło
7

Jednym ze sposobów byłoby utworzenie JsonObject i iterowanie przez parametry. Na przykład

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

Następnie możesz wyodrębnić wartości ziarna, takie jak:

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

Mam nadzieję że to pomoże.

Anand Tuli
źródło
5

Używając Gson do rozwiązania
, utworzyłbym klasę dla poszczególnych parametrów w łańcuchu json. Alternatywnie możesz utworzyć jedną główną klasę o nazwie „Dane”, a następnie w podobny sposób utworzyć klasy wewnętrzne. Dla jasności stworzyłem osobne klasy.

Zajęcia są następujące.

  • Dane
  • Tłumaczenia
  • TranslatedText

W klasie JsonParsing wywoływana jest metoda "parse", gson.fromJson(jsonLine, Data.class)która konwertuje String w obiektach Java przy użyciu Reflection.

Po uzyskaniu dostępu do obiektu „Data” mamy dostęp do każdego parametru indywidualnie.

Nie miałem okazji przetestować tego kodu, ponieważ jestem z dala od mojej maszyny deweloperskiej. Ale to powinno pomóc.

Kilka dobrych przykładów i artykułów.
http://albertattard.blogspot.com/2009/06/practical-example-of-gson.html
http://sites.google.com/site/gson/gson-user-guide

Kod

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;
        }
    }
kensen john
źródło
Nie potrzebujesz seterów do tych klas pomocniczych? Nic nie może ustawić private String translatedTextbez naruszania kontroli dostępu, więc nie ma sposobu, fromJSONaby ustawić go w maszynach JVM, które nie zdecydowały się na odbicie odbiciem deptania całej kontroli dostępu.
Mike Samuel
@Mike Samuel strzelił zupełnie zapomniał o seterach
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")
    }

Prosty przykład analizy JSON w ten sposób

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

Rahul Malhotra
źródło
2

Najpierw wygeneruj metodę pobierającą i ustawiającą za pomocą poniższej witryny parsującej

http://www.jsonschema2pojo.org/

Teraz użyj Gson

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

Teraz użyj obiektu, aby uzyskać wartości, takie jak data, translationText

Nilesh Panchal
źródło
2

Możesz użyć zapytania JsonPath, aby wyodrębnić wartość. A dzięki JsonSurfer, który jest wspierany przez Gson, twój problem można rozwiązać za pomocą zaledwie dwóch linii kodu!

    JsonSurfer jsonSurfer = JsonSurfer.gson();
    String result = jsonSurfer.collectOne(jsonLine, String.class, "$.data.translations[0].translatedText");
Leo Wang
źródło
1

Kod jednowierszowy:

System.out.println(new Gson().fromJson(jsonLine,JsonObject.class).getAsJsonObject().get("data").getAsJsonObject().get("translations").getAsJsonArray().get(0).getAsJsonObject().get("translatedText").getAsString());
retArdos
źródło