Gson如何在单个数组中解析不同的数据类型?

时间:2018-11-05 19:40:42

标签: java android json gson

我有一个API响应,其中包含METAR天气数据以及字符串错误响应,两者都包含在同一“数据”数组中。我正在使用Gson解析Android上的json响应。在收到字符串错误响应之前,此方法效果很好。我已经尽力尝试编写一个没有运气的自定义Gson解串器。有人可以给我一个可行的例子,或为我指出正确的处理方式吗?

响应如下:

{
    "results": 4,
    "data": [
        {
            "icao": "KAJO",
            "name": "Corona Municipal",
            "observed": "05-11-2018 @ 18:56Z",
            "raw_text": "KAJO 051856Z AUTO VRB03KT 10SM CLR 23/08      A2989 RMK AO2 SLP129 T02330078 $",
            "barometer": {
                "hg": 29.890000000000001,
                "kpa": 101.22,
                "mb": 1012.9
            },
            "clouds": [
                {
                    "code": "CLR",
                    "text": "Clear skies",
                    "base_feet_agl": 0,
                    "base_meters_agl": 0
                }
            ],
            "dewpoint": {
                "celsius": 8,
                "fahrenheit": 46
            },
            "elevation": {
                "feet": 535,
                "meters": 163
            },
            "flight_category": "VFR",
            "humidity_percent": 38,
            "temperature": {
                "celsius": 23,
                "fahrenheit": 73
            },
            "visibility": {
                "miles": "10",
                "meters": "16,093"
            },
            "wind": {
                "degrees": 0,
                "speed_kts": 3,
                "speed_mph": 3,
                "speed_mps": 2
            }
        },
        "KGNG METAR Currently Unavailable",
        "CXCY Invalid Station ICAO"
    ]
}

如您所见,“数据”数组可能返回metar对象(我正在处理此部分)或未命名的错误字符串。当我收到返回的错误字符串时,解析失败。

作为测试,我写了以下内容。但这也不起作用。如何解析原始未命名字符串和metar对象?

import com.google.gson.*;

import java.lang.reflect.Type;
import java.util.List;

public class Main {

    public static void main(String[] args) {

        Gson gson = new GsonBuilder()
                .registerTypeAdapter(Response.class, new MyDeserializer())
                .registerTypeAdapter(String.class, new String())
                .create();

        Response response = gson.fromJson(str_json, Response.class);
        System.out.println("Hello World!");
    }

    static class MyDeserializer implements JsonDeserializer<Response> {
        @Override
        public Response deserialize(JsonElement json, Type typeOfT
                ,JsonDeserializationContext context) throws JsonParseException {
            // Get the "data" element from the parsed json
            JsonElement data = json.getAsJsonObject().get("data    ");
            // Deserialize it. You use a new instance of Gson to avoid
            // infinite recursion
            return new Gson().fromJson(data, Response.class);

        }
    }
    /*===============================
     * Data Definitions
     *==============================*/
    class Response {
           public String  results;
           public List<Station> Stations;
    }

    class Station {
        public String name;
        public String icao;
    }

    public static String str_json = "{\n" +
            "    \"results\": 3,\n" +
            "    \"data\": [\n" +
            "        {\n" +
            "           \"name\": \"Billings Logan Intl\"," +
            "           \"icao\":\"KBIL\"," +
            "        },\n" +
            "        \"CYPG METAR Currently Unavailable\",\n" +
            "        \"KGNG METAR Currently Unavailable\"\n" +
            "    ]\n" +
            "}";
}

1 个答案:

答案 0 :(得分:1)

首先,如果您稍微更改DTO,Response

public class Response {
    public String results;
    public List<Station> data; // it is named data in JSON not Stations
}

然后其余的操作取决于您如何处理错误文本。一种简单的方法是将错误字段添加到您的Station中,这样就可以了:

public class Station {
    public String name;
    public String icao;
    public String error;  // used if there is only error string
}

使用自定义反序列化器,例如:

public class StationDeserializer implements JsonDeserializer<Station> {

    private final Gson gson = new Gson();

    @Override
    public Station deserialize(JsonElement json, Type typeOfT
                ,JsonDeserializationContext context)
        throws JsonParseException {         
        try {
            return gson.fromJson(json, Station.class);
        } catch (JsonSyntaxException e) {
            // it was not a Station object
            Station station = new Station();
            // so try to set the error string
            station.error = json.getAsString();
            return station;
        }
    }

}

尝试反序列化:

Response response = new GsonBuilder()
        .registerTypeAdapter(Station.class, new StationDeserializer())
        .create()
        .fromJson(str_json, Response.class);

检查error中是否有Station字符串,您可以查看数据是否有效。