Java Language
JSON w Javie
Szukaj…
Wprowadzenie
JSON (JavaScript Object Notation) to lekki, tekstowy, niezależny od języka format wymiany danych, który jest łatwy do odczytania i zapisu przez ludzi i maszyny. JSON może reprezentować dwa typy strukturalne: obiekty i tablice. JSON jest często używany w aplikacjach, konfiguracjach, bazach danych i usługach sieciowych RESTful Ajax. Interfejs API Java dla JSON Processing zapewnia przenośne interfejsy API do analizowania, generowania, przekształcania i odpytywania JSON.
Uwagi
Ten przykład koncentruje się na analizie i tworzeniu JSON w Javie przy użyciu różnych bibliotek, takich jak biblioteka Google Gson , Jackson Object Mapper i inne ..
Przykłady korzystania z innych bibliotek można znaleźć tutaj: Jak analizować JSON w Javie
Kodowanie danych jako JSON
Jeśli chcesz utworzyć obiekt JSONObject
i umieścić w nim dane, rozważ następujący przykład:
// Create a new javax.json.JSONObject instance.
JSONObject first = new JSONObject();
first.put("foo", "bar");
first.put("temperature", 21.5);
first.put("year", 2016);
// Add a second object.
JSONObject second = new JSONObject();
second.put("Hello", "world");
first.put("message", second);
// Create a new JSONArray with some values
JSONArray someMonths = new JSONArray(new String[] { "January", "February" });
someMonths.put("March");
// Add another month as the fifth element, leaving the 4th element unset.
someMonths.put(4, "May");
// Add the array to our object
object.put("months", someMonths);
// Encode
String json = object.toString();
// An exercise for the reader: Add pretty-printing!
/* {
"foo":"bar",
"temperature":21.5,
"year":2016,
"message":{"Hello":"world"},
"months":["January","February","March",null,"May"]
}
*/
Dekodowanie danych JSON
Jeśli potrzebujesz uzyskać dane z obiektu JSONObject
, rozważ następujący przykład:
String json = "{\"foo\":\"bar\",\"temperature\":21.5,\"year\":2016,\"message\":{\"Hello\":\"world\"},\"months\":[\"January\",\"February\",\"March\",null,\"May\"]}";
// Decode the JSON-encoded string
JSONObject object = new JSONObject(json);
// Retrieve some values
String foo = object.getString("foo");
double temperature = object.getDouble("temperature");
int year = object.getInt("year");
// Retrieve another object
JSONObject secondary = object.getJSONObject("message");
String world = secondary.getString("Hello");
// Retrieve an array
JSONArray someMonths = object.getJSONArray("months");
// Get some values from the array
int nMonths = someMonths.length();
String february = someMonths.getString(1);
metody optXXX a metody getXXX
JSONObject
i JSONArray
mają kilka metod, które są bardzo przydatne podczas radzenia sobie z możliwością, że wartość, którą próbujesz uzyskać, nie istnieje lub jest innego typu.
JSONObject obj = new JSONObject();
obj.putString("foo", "bar");
// For existing properties of the correct type, there is no difference
obj.getString("foo"); // returns "bar"
obj.optString("foo"); // returns "bar"
obj.optString("foo", "tux"); // returns "bar"
// However, if a value cannot be coerced to the required type, the behavior differs
obj.getInt("foo"); // throws JSONException
obj.optInt("foo"); // returns 0
obj.optInt("foo", 123); // returns 123
// Same if a property does not exist
obj.getString("undefined"); // throws JSONException
obj.optString("undefined"); // returns ""
obj.optString("undefined", "tux"); // returns "tux"
Te same zasady stosuje się do getXXX
/ optXXX
metod JSONArray
.
Object To JSON (Gson Library)
Załóżmy, że masz klasę o nazwie Person
z tylko name
private class Person {
public String name;
public Person(String name) {
this.name = name;
}
}
Kod:
Gson g = new Gson();
Person person = new Person("John");
System.out.println(g.toJson(person)); // {"name":"John"}
Oczywiście słoik Gson musi znajdować się na ścieżce klas.
JSON To Object (Gson Library)
Załóżmy, że masz klasę o nazwie Person
z tylko name
private class Person {
public String name;
public Person(String name) {
this.name = name;
}
}
Kod:
Gson gson = new Gson();
String json = "{\"name\": \"John\"}";
Person person = gson.fromJson(json, Person.class);
System.out.println(person.name); //John
Musisz mieć bibliotekę gson w swojej ścieżce klasy.
Wyodrębnij pojedynczy element z JSON
String json = "{\"name\": \"John\", \"age\":21}";
JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
System.out.println(jsonObject.get("name").getAsString()); //John
System.out.println(jsonObject.get("age").getAsInt()); //21
Korzystanie z Jackson Object Mapper
Pojo Model
public class Model {
private String firstName;
private String lastName;
private int age;
/* Getters and setters not shown for brevity */
}
Przykład: ciąg do obiektu
Model outputObject = objectMapper.readValue(
"{\"firstName\":\"John\",\"lastName\":\"Doe\",\"age\":23}",
Model.class);
System.out.println(outputObject.getFirstName());
//result: John
Przykład: Object to String
String jsonString = objectMapper.writeValueAsString(inputObject));
//result: {"firstName":"John","lastName":"Doe","age":23}
Detale
Wymagane oświadczenie importu:
import com.fasterxml.jackson.databind.ObjectMapper;
Zależność Maven: jackson-databind
Instancja ObjectMapper
//creating one
ObjectMapper objectMapper = new ObjectMapper();
-
ObjectMapper
jest wątkowo bezpieczny - zalecane: mieć wspólną, statyczną instancję
Deserializacja:
<T> T readValue(String content, Class<T> valueType)
-
valueType
musi być określony - zwracany będzie ten typ - Rzuty
-
IOException
- w przypadku problemu niskiego poziomu we / wy -
JsonParseException
- jeśli podstawowe dane wejściowe zawierają niepoprawną treść -
JsonMappingException
- jeśli wejściowa struktura JSON nie pasuje do struktury obiektu
-
Przykład użycia (jsonString jest łańcuchem wejściowym):
Model fromJson = objectMapper.readValue(jsonString, Model.class);
Metoda serializacji:
String writeValueAsString (wartość obiektu)
- Rzuty
-
JsonProcessingException
w przypadku błędu - Uwaga: przed wersją 2.1 klauzula rzucania zawierała wyjątek IOException; 2.1 usunął go.
-
Iteracja JSON
JSONObject
właściwościach JSONObject
JSONObject obj = new JSONObject("{\"isMarried\":\"true\", \"name\":\"Nikita\", \"age\":\"30\"}");
Iterator<String> keys = obj.keys();//all keys: isMarried, name & age
while (keys.hasNext()) { //as long as there is another key
String key = keys.next(); //get next key
Object value = obj.get(key); //get next value by key
System.out.println(key + " : " + value);//print key : value
}
JSONArray
wartościach JSONArray
JSONArray arr = new JSONArray(); //Initialize an empty array
//push (append) some values in:
arr.put("Stack");
arr.put("Over");
arr.put("Flow");
for (int i = 0; i < arr.length(); i++) {//iterate over all values
Object value = arr.get(i); //get value
System.out.println(value); //print each value
}
JSON Builder - metody łączenia
Podczas pracy z JSONObject
i JSONArray
można używać łączenia łańcuchowego JSONArray
.
Przykład JSONObject
JSONObject obj = new JSONObject();//Initialize an empty JSON object
//Before: {}
obj.put("name","Nikita").put("age","30").put("isMarried","true");
//After: {"name":"Nikita","age":30,"isMarried":true}
JSONArray
JSONArray arr = new JSONArray();//Initialize an empty array
//Before: []
arr.put("Stack").put("Over").put("Flow");
//After: ["Stack","Over","Flow"]
JSONObject.NULL
Aby dodać właściwość o wartości null
, należy użyć wstępnie zdefiniowanego statycznego końcowego JSONObject.NULL
a nie standardowego odwołania Java o null
.
JSONObject.NULL
jest wartością wartownika używaną do jawnego zdefiniowania właściwości o pustej wartości.
JSONObject obj = new JSONObject();
obj.put("some", JSONObject.NULL); //Creates: {"some":null}
System.out.println(obj.get("some"));//prints: null
Uwaga
JSONObject.NULL.equals(null); //returns true
Co jest wyraźnym naruszeniem umowy Java.equals()
:
Dla każdej wartości odniesienia innej niż null x, x.equals (null) powinno zwracać wartość false
JsonArray to Java List (Gson Library)
Oto prosty JsonArray, który chciałbyś przekonwertować na Java ArrayList
:
{
"list": [
"Test_String_1",
"Test_String_2"
]
}
Teraz JsonArray
„listę” JsonArray
do następującej metody, która zwraca odpowiednią listę ArrayList
Java:
public ArrayList<String> getListString(String jsonList){
Type listType = new TypeToken<List<String>>() {}.getType();
//make sure the name 'list' matches the name of 'JsonArray' in your 'Json'.
ArrayList<String> list = new Gson().fromJson(jsonList, listType);
return list;
}
Do pliku POM.xml
należy dodać następującą zależność maven:
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.7</version>
</dependency>
Lub powinieneś mieć słoik com.google.code.gson:gson:jar:<version>
w ścieżce klasy.
Deserializuj kolekcję JSON do kolekcji obiektów za pomocą Jacksona
Załóżmy, że masz klasę pojo Person
public class Person {
public String name;
public Person(String name) {
this.name = name;
}
}
I chcesz parsować go do tablicy JSON lub mapy obiektów Person. Z powodu usunięcia typu nie można bezpośrednio tworzyć klas List<Person>
i Map<String, Person>
w środowisku wykonawczym (a tym samym używać ich do deserializacji JSON) . Aby pokonać to ograniczenie, Jackson oferuje dwa podejścia - TypeFactory
i TypeReference
.
TypeFactory
Podejście tutaj polega na użyciu fabryki (i jej statycznej funkcji użyteczności), aby zbudować swój typ dla ciebie. Wymagane parametry to kolekcja, której chcesz użyć (lista, zestaw itp.) Oraz klasa, którą chcesz przechowywać w tej kolekcji.
TypeReference
Podejście do typowania wydaje się prostsze, ponieważ pozwala zaoszczędzić trochę pisania i wygląda na czystsze. TypeReference akceptuje parametr typu, w którym przekazujesz pożądany typ List<Person>
. Wystarczy utworzyć instancję tego obiektu TypeReference i użyć go jako kontenera typu.
Teraz przyjrzyjmy się, jak dokonać deserializacji JSON w obiekt Java. Jeśli Twój JSON jest sformatowany jako tablica, możesz dokonać deserializacji jako List. Jeśli istnieje bardziej złożona struktura zagnieżdżona, należy dokonać deserializacji na mapę. Przyjrzymy się przykładom obu.
Deserializowanie tablicy JSON
String jsonString = "[{\"name\": \"Alice\"}, {\"name\": \"Bob\"}]"
Podejście TypeFactory
CollectionType listType =
factory.constructCollectionType(List.class, Person.class);
List<Preson> list = mapper.readValue(jsonString, listType);
Podejście TypeReference
TypeReference<Person> listType = new TypeReference<List<Person>>() {};
List<Person> list = mapper.readValue(jsonString, listType);
Deserializowanie mapy JSON
String jsonString = "{\"0\": {\"name\": \"Alice\"}, \"1\": {\"name\": \"Bob\"}}"
Podejście TypeFactory
CollectionType mapType =
factory.constructMapLikeType(Map.class, String.class, Person.class);
List<Person> list = mapper.readValue(jsonString, mapType);
Podejście TypeReference
TypeReference<Person> mapType = new TypeReference<Map<String, Person>>() {};
Map<String, Person> list = mapper.readValue(jsonString, mapType);
Detale
Zastosowana instrukcja importu:
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
Użyte wystąpienia:
ObjectMapper mapper = new ObjectMapper();
TypeFactory factory = mapper.getTypeFactory();
Uwaga
Chociaż podejście TypeReference
może wyglądać lepiej, ma kilka wad:
-
TypeReference
należy utworzyć za pomocą klasy anonimowej - Powinieneś zapewnić ogólne wyjaśnienie
Niezastosowanie się do tego może prowadzić do utraty argumentu typu ogólnego, co doprowadzi do niepowodzenia deserializacji.