Разбор вложенных узлов JSON в POJO с помощью Google Http Java Client
Например, у меня есть ответ со следующим JSON:
{
response: {
id: 20,
name: Stas
}
}
И я хочу разобрать его на следующий объект:
class User {
private int id;
private String name;
}
Как пропустить узел ответа?
Я использую Google Http Java Client, и будет хорошо, если кто-нибудь ответит, как это сделать. Как эти линии изменились?
request.setParser(new JacksonFactory().createJsonObjectParser());
return request.execute().parseAs(getResultType());
3 ответа
Теперь вы можете реализовать это за один шаг:
new JsonObjectParser.Builder(jsonFactory)
.setWrapperKeys(Arrays.asList("response"))
.build()
http://javadoc.google-http-java-client.googlecode.com/hg/1.15.0-rc/index.html
Я не нашел родной способ (для этой библиотеки) решить мою задачу. В результате я решил эту проблему, расширив функциональность JsonObjectParser. Это влечет за собой расширение JacksonFactory, но это последний класс, поэтому я использовал агрегацию.
Я написал следующие классы:
JacksonFilteringFactory
import com.google.api.client.json.JsonObjectParser; import com.google.api.client.json.jackson2.JacksonFactory; public class JacksonFilteringFactory { private final JacksonFactory factory = new JacksonFactory(); public JsonObjectParser createJsonObjectParser(String filteringNode) { return new FilteringJsonObjectParser(factory, filteringNode); } }
FilteringJsonObjectParser
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Type; import java.nio.charset.Charset; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; import com.google.api.client.json.JsonFactory; import com.google.api.client.json.JsonObjectParser; import com.vkredmessenger.AppController; import com.vkredmessenger.util.StringUtils; public class FilteringJsonObjectParser extends JsonObjectParser { private String mFilteringNode; public FilteringJsonObjectParser(JsonFactory jsonFactory, String filteringNode) { super(jsonFactory); mFilteringNode = filteringNode; } @Override public Object parseAndClose(InputStream in, Charset charset, Type dataType) throws IOException { String originalResponse = StringUtils.convertStreamToString(in, charset); String response = null; try { JSONTokener tokener = new JSONTokener(originalResponse); JSONObject originalResponseObject = (JSONObject) tokener.nextValue(); JSONObject responseObject = originalResponseObject.getJSONObject(mFilteringNode); response = responseObject.toString(); } catch (JSONException e) { e.printStackTrace(); } InputStream filteredIn = new ByteArrayInputStream(response.getBytes(charset)); return super.parseAndClose(filteredIn, charset, dataType); } }
Так, например, из моего вопроса, результат анализа кода будет следующим:
request.setParser(new JacksonFilteringFactory().createJsonObjectParser("response"));
return request.execute().parseAs(getResultType());
Я не знаю Java Http-клиент Google, но если вы можете получить доступ к Jackson ObjectMapper, вы можете сделать следующее:
1.) Включить распаковку корня:
objectMapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
2.) Добавить аннотацию к User.class:
@JsonRootName("response")
class User {
…
}
Я надеюсь, что вы можете использовать этот подход.
Изменить: я копался в API google-http-java-client и пришел к выводу, что вы не можете получить прямой доступ к ObjectMapper. Чтобы использовать всю мощь Джексона, вам нужно написать собственную реализацию JsonObjectParser, чтобы обернуть "настоящий" парсер Джексона. Извините за это, может быть, кто-то еще может найти лучшее решение.