Возник вопрос насчет разбора JSON. Пока что я получаю данные в виде строки. Я бы хотел распарсить в класс через Gson
. Дело в том что название заголовка 179746
меняется. Оно может принимать другое имя, все остальное не меняется. Использую для генерации класса jsonschema2pojo , ну если у нас название заголовка становится 10000
, то класс сразу становится не используемым
{
"status": "ok",
"meta": {
"count": 1
},
"data": {
"179746": {
"leader_id": 3239400
}
}
}
Может можно как-то убрать тут 179746, и подставить общий параметр, я не знаю как делать.
public class Data {
@SerializedName("179746")
@Expose
private com.example._179746 _179746;
public com.example._179746 get179746() {
return _179746;
}
public void set179746(com.example._179746 _179746) {
this._179746 = _179746;
}
Пока что я делаю так
jsonObject = new JSONObject(getResponse);
JSONObject jsonObject1 = jsonObject.getJSONObject("data");
JSONObject json = jsonObject1.getJSONObject("179746");
Если бы jsonschema2pojo не использовали, количество вопросов связанных с Gson на SO резко бы сократилось вдвое. На это есть следующие причины:
List
, Map
и т.д.;Кроме того, в Gson не существует JSON***
-- типов с заглавными "JSON" в имени. Это из org.json, в то время как в Gson всегда -- Json***
. Дальше, если вы уж и собрались использовать маппинги, их можно использовать почти во всех случаях, и не смешивать их с сущностями, которые представляют JSON-объекты в памяти в виде древовидных структур (т.е., всё семейство JsonElement
). Ещё: для объектов с динамическими именами в Gson существует родная поддержка Map<K,V>
(впрочем, это справедливо и для Java, поскольку количество имён не известно заранее на этапе компиляции).
Резюмируя вышесказанное, в этом случае нужно просто написать правильные маппинги.
final class Response<T> {
final String status = null;
final Meta meta = null;
final T data = null;
}
final class Meta {
final int count = Integer.valueOf(0);
}
final class Leader {
@SerializedName("leader_id")
final int leaderId = Integer.valueOf(0);
}
Чем это отличается от того, что генерирует тот сервис:
Response<T>
);@SerializedName
и нет @Expose
-- с одной стороны это спорно и противоречит "явному, которое лучше неявного"; с другой -- меньше шума;set***
/get***
) -- объекты, предназначенные исключительно для переноса данных между компонентами системы (DTO) и которые должны использоваться исключительно сопутствующими компонентами могут опускать это требование хорошего тона, поскольку здесь и инкапсулировать-то нечего;final
-- изменяться же не должно (Gson отлично справляется с классами без конструкторов и умеет изменять final
-поля во время исполнения; исключение из такого "паттерна": примитивным типам как int
не могут присваиватся значения по-умолчанию типа = 0
, потому что компилятор просто заинлайнит это значения, и у Gson не будет возможности изменить поле (точнее, места, в которые эта константа заинлайнена) -- поэтому Integer.valueOf(0)
является своего рода хаком, чтобы ослепить компилятор).Пример использования:
private static final Gson gson = new Gson();
private static final Type leaderMapResponseType = new TypeToken<Response<Map<Integer, Leader>>>() {
}.getType();
public static void main(final String... args)
throws IOException {
try ( final Reader reader = getPackageResourceReader(Q660527.class, "response.json") ) {
final Response<Map<Integer, Leader>> response = gson.fromJson(reader, leaderMapResponseType);
System.out.println(response.status);
System.out.println(response.meta.count);
for ( final Entry<Integer, Leader> e : response.data.entrySet() ) {
System.out.println(e.getKey() + " => " + e.getValue().leaderId);
}
}
}
Инстансы Gson
и Type
(по крайней мере те, что порождены с использованием TypeToken<T>
) могут считаться иммутабельными и потокобезопасными, поэтому их можно закешировать, не прибегая к повторному созданию экземпляров с теми же характеристиками. Пару слов о том, что такое "type token"-ы. В Java из-за специфики реализации дженериков не существует возможности написать Response<Map<String,Leader>>.class
, потому что Class<T>
не содержат информации об актуальной параметризации за исключением параметризации родительского класса при наследовании. Возможно, было б очень круто, если бы в Java можно было создавать ad-hoc реализации Type
/ParameterizedType
примерно как Response<Map<String,Leader>>.type
, но увы. Как Gson решает эту проблему? Как я сказал выше, параметризация сохраняется при наследовании, поэтому Gson требует хотя бы анонимной реализации класса TypeToken<T>
. При создании экземпляра TypeToken<T>
Gson имеет достаточно информации о том, как параметризирован Response<T>
, и его вызов getType()
возвращает уже проанализированную информацию о параметризированном типе, а не просто о классе. Это эквивалентно ручной реализации ParameterizedType
, но с помощью предыдущего механизма запись немножко короче и красивее. И да: "type token"-ы не нужны, если например информация о параметризации уже доступна, например, из типа поля в каком-нибудь классе (т.е., обычный private final Map<String, Float> map;
уже содержит достаточно информации о типе (класс по прежнему -- просто Map
)).
Результат вывода:
ok
1
179746 => 3239400
Может вам сначала получить название через строку и потом его использовать
int startIndex = getResponse.indexOf("\"data\": {")+9;
int endIndex = getResponse.indexOf("\": {", startIndex);
String nameAfterData = getResponse.subString(startIndex, endIndex);
и потом просто использовать имя JSON объекта пр парсинге?
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Необходимо, чтобы определенный список текста циклично менялся аккуратной анимацией по времениСейчас вот такая картина, из-за чего список...
У меня на Landing'e блок типа хедера находится слева, и он должен продолжаться на весь landingУже пробовал по разному, но кроме фиксированной высоты...