Gson, JSON и тонкости LinkedTreeMap
Я недавно начал играть с JSON
строки, и было сказано, что собственная библиотека Google,Gson
, это новый и хип-способ борьбы с этими.
насколько я понял, это JSON
строка по существу является картой. Где каждая переменная указывает на значение в строке.
например:
String jsonInput2 = "{"created_at":"Sat Feb 08 15:37:37 +0000 2014","id":432176397474623489"}
пока все хорошо. Информация, например, когда это JSON
строка была создана, может быть назначена переменной с следующий код:
Gson gson = new Gson();
Map<String, String> map = new HashMap<String, String>();
map = (Map<String, String>) gson.fromJson(jsonInput, map.getClass());
String createdAt = map.get("created_at");
это почти художественно в простой красоте. Но здесь красота заканчивается, и начинается мое замешательство.
следующее является расширением выше JSON
строка
String jsonInput2 = "{"created_at":"Sat Feb 08 15:37:37 +0000 2014","id":432176397474623489","user":{"id_str":"366301747","name":"somethingClever","screen_name":"somethingCoolAndClever"}}";
мой вопрос в том, как эти "скобки в скобках" работа для на JSON
?
как я могу присвоить значения, указанные в этих внутренних скобок к переменным?
может кто-нибудь объяснить мне, или покажите мне в коде как Gson
обрабатывает такие вещи, и как я могу его использовать?
короче, Почему...
String jsonInput = "{"created_at":"Sat Feb 08 15:37:37 +0000 2014","id":432176397474623489","user":{"id_str":"366301747","name":"somethingClever","screen_name":"somethingCoolAndClever"}}";
Gson gson = new Gson();
Map<String, String> map = new HashMap<String, String>();
map = (Map<String, String>) gson.fromJson(jsonInput, map.getClass());
String name = map.get("name");
System.out.println(name);
... распечатать null
?
5 ответов
забудьте о Java. Вы должны сначала понять формат JSON. Это в основном это
object
{}
{ members }
members
pair
pair , members
pair
string : value
array
[]
[ elements ]
elements
value
value , elements
value
string
number
object
array
true
false
null
ваш второй JSON String
(у которого отсутствует "
) следующее (используйте jsonlint.com форматировать)
{
"created_at": "Sat Feb 08 15:37:37 +0000 2014",
"id": "432176397474623489",
"user": {
"id_str": "366301747",
"name": "somethingClever",
"screen_name": "somethingCoolAndClever"
}
}
JSON-это объект, внешний {}
, который содержит три пары, created_at
который является строкой JSON,id
который также является строкой JSON и user
который является объектом JSON. Этот объект JSON содержит еще три пары все строки JSON.
Вы спрашивали
как я могу присвоить значения, указанные в этих внутренних скобках переменные?
большинство продвинутых библиотек JSON-анализа/генерации предназначены для преобразования JSON в Pojos и обратно.
таким образом, вы можете сопоставить формат JSON с классами Java.
class Pojo {
@SerializedName("created_at")
private String createdAt;
private String id;
private User user;
}
class User {
@SerializedName("id_str")
private String idStr;
private String name;
@SerializedName("screen_name")
private String screenName;
}
// with appropriate getters, setters, and a toString() method
Примечание @SerializedName
чтобы вы могли продолжать использовать Соглашения об именах Java для вашего поля.
теперь вы можете десериализовать JSON в код
Gson gson = new Gson();
Pojo pojo = gson.fromJson(jsonInput2, Pojo.class);
System.out.println(pojo);
печати
Pojo [createdAt=Sat Feb 08 15:37:37 +0000 2014, id=432176397474623489", user=User [idStr=366301747, name=somethingClever, screenName=somethingCoolAndClever]]
показывает, что все поля были правильно установлены.
может ли кто-нибудь объяснить мне или показать мне в коде, как Gson обрабатывает такие вещи, и как я могу их использовать?
исходный код Gson находится в свободном доступе. Вы можете найти его в интернете. Это сложно, и объяснение исходного кода здесь не подходит. Проще говоря, он использует Class
объект, который вы предоставляете, чтобы определить, как он будет отображать пары JSON. Он смотрит на поля соответствующего класса. Если эти поля являются другими классами, то он повторяется, пока не построит карту всего, что ему нужно десериализовать.
короче, Почему...распечатать значение null?
потому что ваш корневой объект JSON не имеет пары с именем name
. Вместо использования Map
используйте Дсын это JsonObject
тип.
JsonObject jsonObject = new Gson().fromJson(jsonInput2, JsonObject.class);
String name = jsonObject.get("user") // get the 'user' JsonElement
.getAsJsonObject() // get it as a JsonObject
.get("name") // get the nested 'name' JsonElement
.getAsString(); // get it as a String
System.out.println(name);
, который печатает
somethingClever
вышеуказанный класс метода мог бы создать ряд исключений, если бы они не были правильным типом. Если бы, например, мы сделали
String name = jsonObject.get("user") // get the 'user' JsonElement
.getAsJsonArray() // get it as a JsonArray
это не так user
не является массивом JSON. В частности, он будет бросать
Exception in thread "main" java.lang.IllegalStateException: This is not a JSON Array.
at com.google.gson.JsonElement.getAsJsonArray(JsonElement.java:106)
at com.spring.Example.main(Example.java:19)
так JsonElement
class (который является родительским классом JsonObject
, JsonArray
и несколько других) предоставляет методы для проверки того, что это такое. Увидеть документация Javadoc.
строка JSON имеет следующую структуру:
{
created_at: "",
id: "",
user: {
id_str: "",
name: "",
screen_name: ""
}
}
когда вы помещаете значения в карту, используя код:
Map<String, Object> map = new HashMap<String, Object>();
map = (Map<String, Object>) gson.fromJson(jsonInput, map.getClass());
он имеет следующие основные значения:
created_at
id
user
и поэтому вы можете использовать map.get("created_at")
.
теперь, поскольку вы хотите получить имя пользователя, вам нужно получить карту пользователя:
LinkedTreeMap<String, Object> userMap = (LinkedTreeMap<String, Object>) map.get("user");
на userMap
, вы получите следующие ключевые значения:
id_str
name
screen_name
теперь, вы можете получить name
на user
String name = userMap.get("name");
для людей, которые приходят сюда в поисках пути к преобразовать LinkedTreeMap в object:
MyClass object = new Gson().fromJson(new Gson().toJson(((LinkedTreeMap<String, Object>) theLinkedTreeMapObject)), MyClass .class)
Это было полезно для меня, когда мне нужно было разобрать общий объект, такой как:
Class fullObject {
private String name;
private String objectType;
private Object objectFull;
}
но я не знаю, какой объект сервер собирался отправить. ObjectFull станет LinkedTreeMap
Ok. Прежде всего, JSON является сокращением от "JavaScript Object Notation", поэтому ваше утверждение о том, что "строка JSON по существу является картой" неверно. Блок JSON-это объектный граф, описываемый с помощью синтаксиса языка JavaScript. Поскольку вы пытаетесь принудить граф объектов к отображению пар значений String, Sting kay, это будет работать только в тех случаях, когда любой данный граф объектов JSON по существу является именно этим (так что не очень часто). Более успешной была бы стратегия gson.fromJson()
Что будет преобразуйте JSON в правильный график объектов Java.