Gson - 在将JSON解析为Object时忽略json字段

时间:2015-02-10 02:53:39

标签: java android json gson

有一个问题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字段左侧的字段。

1 个答案:

答案 0 :(得分:7)

我认为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来制作轻物体,并且只使用我感兴趣的字段。听起来像是正确的方法。

现在,如果您确实只想检索距离列表,我们确定您可以使用自定义TypeAdapterTypeAdapterFactory进行检索。

类似的东西(坏方法: - )):

映射响应的对象:

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树,然后将检索所需的JsonObject以通过委托创建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

希望它有所帮助。