Gson - 在将 JSON 解析为对象时忽略 json 字段
Gson - ignore json fields when parsing JSON to Object
有一个问题 here 与我的问题相似,但不完全是我要找的问题。
我有一个来自网络服务的 JSON 响应,比方说 this JSON response:
{
"routes" : [
{
"bounds" : {
"northeast" : {
"lat" : 45.5017123,
"lng" : -73.5672184
},
"southwest" : {
"lat" : 43.6533103,
"lng" : -79.3827675
}
},
"copyrights" : "Dados do mapa ©2015 Google",
"legs" : [
{
"distance" : {
"text" : "541 km",
"value" : 540536
},
"duration" : {
"text" : "5 horas 18 min.",
"value" : 19058
},
"end_address" : "Montreal, QC, Canada",
"end_location" : {
"lat" : 45.5017123,
"lng" : -73.5672184
},
"start_address" : "Toronto, ON, Canada",
"start_location" : {
"lat" : 43.6533103,
"lng" : -79.3827675
},
(...)
在这个 JSON 中,我只对 distance
对象感兴趣。我的问题是,如何忽略所有其他字段?
我尝试从 legs
开始构建我的对象,因为它是从 distance
到根的第一个非重复对象名称。
这是我的对象:
public class MyObject {
public ArrayList<Distance> legs;
public static class Distance {
public String text;
public String value;
}
}
但 ArrayList legs
始终是 null
。
我怎样才能做到这一点?忽略假 json 字段左侧的字段。
我认为 Gson 的理念是将 Json 结构映射到对象图。所以在你的情况下,我可能会创建所有需要的 java 对象来正确映射 json 结构。除此之外,也许有一天你会需要一些其他的响应信息,这样演化就会更容易。类似的东西(我认为正确的方式):
class RouteResponse {
private List<Route> routes;
}
class Route {
private List<Bound> bounds;
private String copyrights;
private List<Leg> legs;
}
class Leg {
private Distance distance;
private Duration duration;
private String endAddress;
...
}
class TextValue {
private String text;
private String value;
}
class Distance extends TextValue {
}
// And so on
而且我会使用 ExclusionStrategy 来拥有光对象并且只拥有我感兴趣的字段。在我看来这是正确的方法。
现在,如果您真的只想检索距离列表,我相信您可以使用自定义 TypeAdapter and TypeAdapterFactory。
类似的东西(糟糕的方式:-)):
要映射响应的对象:
public class RouteResponse {
private List<Distance> distances;
// add getters / setters
}
public class Distance {
private String text;
private String value;
// add getters / setters
}
实例化适配器的工厂(引用 Gson
对象,因此适配器可以检索委托):
public class RouteResponseTypeAdapterFactory implements TypeAdapterFactory {
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (type.getRawType() == RouteResponse.class) {
return (TypeAdapter<T>)new RouteResponseTypeAdapter(gson);
}
return null;
}
}
和类型适配器:此实现首先将 Json 文档解组为 JsonElement
s 树,然后检索所需的 JsonObject
s 以通过委托创建 Distance
对象(抱歉代码不好,写的很快)。
public class RouteResponseTypeAdapter extends TypeAdapter<RouteResponse> {
private final TypeAdapter<JsonElement> jsonElementTypeAdapter;
private final TypeAdapter<Distance> distanceTypeAdapter;
public RouteResponseTypeAdapter(Gson gson) {
this.jsonElementTypeAdapter = gson.getAdapter(JsonElement.class);
this.distanceTypeAdapter = gson.getAdapter(Distance.class);
}
@Override
public void write(JsonWriter out, RouteResponse value) throws IOException {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public RouteResponse read(JsonReader jsonReader) throws IOException {
RouteResponse result = new RouteResponse();
List<Distance> distances = new ArrayList<>();
result.setDistances(distances);
if (jsonReader.peek() == JsonToken.BEGIN_OBJECT) {
JsonObject responseObject = (JsonObject) jsonElementTypeAdapter.read(jsonReader);
JsonArray routes = responseObject.getAsJsonArray("routes");
if (routes != null) {
for (JsonElement element:routes) {
JsonObject route = element.getAsJsonObject();
JsonArray legs = route.getAsJsonArray("legs");
if (legs != null) {
for (JsonElement legElement:legs) {
JsonObject leg = legElement.getAsJsonObject();
JsonElement distanceElement = leg.get("distance");
if (distanceElement != null) {
distances.add(distanceTypeAdapter.fromJsonTree(distanceElement));
}
}
}
}
}
}
return result;
}
}
最后,您可以解析您的 json 文档:
String json = "{ routes: [ ....."; // Json document
Gson gson = new GsonBuilder().registerTypeAdapterFactory(new RouteResponseTypeAdapterFactory()).create();
RouteResponse response = gson.fromJson(json, RouteResponse.class);
//response.getDistances() should contain the distances
希望对您有所帮助。
有一个问题 here 与我的问题相似,但不完全是我要找的问题。
我有一个来自网络服务的 JSON 响应,比方说 this JSON response:
{
"routes" : [
{
"bounds" : {
"northeast" : {
"lat" : 45.5017123,
"lng" : -73.5672184
},
"southwest" : {
"lat" : 43.6533103,
"lng" : -79.3827675
}
},
"copyrights" : "Dados do mapa ©2015 Google",
"legs" : [
{
"distance" : {
"text" : "541 km",
"value" : 540536
},
"duration" : {
"text" : "5 horas 18 min.",
"value" : 19058
},
"end_address" : "Montreal, QC, Canada",
"end_location" : {
"lat" : 45.5017123,
"lng" : -73.5672184
},
"start_address" : "Toronto, ON, Canada",
"start_location" : {
"lat" : 43.6533103,
"lng" : -79.3827675
},
(...)
在这个 JSON 中,我只对 distance
对象感兴趣。我的问题是,如何忽略所有其他字段?
我尝试从 legs
开始构建我的对象,因为它是从 distance
到根的第一个非重复对象名称。
这是我的对象:
public class MyObject {
public ArrayList<Distance> legs;
public static class Distance {
public String text;
public String value;
}
}
但 ArrayList legs
始终是 null
。
我怎样才能做到这一点?忽略假 json 字段左侧的字段。
我认为 Gson 的理念是将 Json 结构映射到对象图。所以在你的情况下,我可能会创建所有需要的 java 对象来正确映射 json 结构。除此之外,也许有一天你会需要一些其他的响应信息,这样演化就会更容易。类似的东西(我认为正确的方式):
class RouteResponse {
private List<Route> routes;
}
class Route {
private List<Bound> bounds;
private String copyrights;
private List<Leg> legs;
}
class Leg {
private Distance distance;
private Duration duration;
private String endAddress;
...
}
class TextValue {
private String text;
private String value;
}
class Distance extends TextValue {
}
// And so on
而且我会使用 ExclusionStrategy 来拥有光对象并且只拥有我感兴趣的字段。在我看来这是正确的方法。
现在,如果您真的只想检索距离列表,我相信您可以使用自定义 TypeAdapter and TypeAdapterFactory。
类似的东西(糟糕的方式:-)):
要映射响应的对象:
public class RouteResponse {
private List<Distance> distances;
// add getters / setters
}
public class Distance {
private String text;
private String value;
// add getters / setters
}
实例化适配器的工厂(引用 Gson
对象,因此适配器可以检索委托):
public class RouteResponseTypeAdapterFactory implements TypeAdapterFactory {
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (type.getRawType() == RouteResponse.class) {
return (TypeAdapter<T>)new RouteResponseTypeAdapter(gson);
}
return null;
}
}
和类型适配器:此实现首先将 Json 文档解组为 JsonElement
s 树,然后检索所需的 JsonObject
s 以通过委托创建 Distance
对象(抱歉代码不好,写的很快)。
public class RouteResponseTypeAdapter extends TypeAdapter<RouteResponse> {
private final TypeAdapter<JsonElement> jsonElementTypeAdapter;
private final TypeAdapter<Distance> distanceTypeAdapter;
public RouteResponseTypeAdapter(Gson gson) {
this.jsonElementTypeAdapter = gson.getAdapter(JsonElement.class);
this.distanceTypeAdapter = gson.getAdapter(Distance.class);
}
@Override
public void write(JsonWriter out, RouteResponse value) throws IOException {
throw new UnsupportedOperationException("Not implemented");
}
@Override
public RouteResponse read(JsonReader jsonReader) throws IOException {
RouteResponse result = new RouteResponse();
List<Distance> distances = new ArrayList<>();
result.setDistances(distances);
if (jsonReader.peek() == JsonToken.BEGIN_OBJECT) {
JsonObject responseObject = (JsonObject) jsonElementTypeAdapter.read(jsonReader);
JsonArray routes = responseObject.getAsJsonArray("routes");
if (routes != null) {
for (JsonElement element:routes) {
JsonObject route = element.getAsJsonObject();
JsonArray legs = route.getAsJsonArray("legs");
if (legs != null) {
for (JsonElement legElement:legs) {
JsonObject leg = legElement.getAsJsonObject();
JsonElement distanceElement = leg.get("distance");
if (distanceElement != null) {
distances.add(distanceTypeAdapter.fromJsonTree(distanceElement));
}
}
}
}
}
}
return result;
}
}
最后,您可以解析您的 json 文档:
String json = "{ routes: [ ....."; // Json document
Gson gson = new GsonBuilder().registerTypeAdapterFactory(new RouteResponseTypeAdapterFactory()).create();
RouteResponse response = gson.fromJson(json, RouteResponse.class);
//response.getDistances() should contain the distances
希望对您有所帮助。