首页 > 解决方案 > 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"
    ]
}

如您所见,“数据”数组可能会返回一个元对象(我有这部分工作)或一个未命名的错误字符串。当我收到返回的错误字符串时,我的解析失败了。

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

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" +
            "}";
}

标签: javaandroidjsongson

解决方案


首先,如果您稍微更改一下 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);

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


推荐阅读