将Json解析为Java对象

4

我很少使用Json,但是我需要将一个复杂的Json解析成Java对象。

我尝试了几种方法,但都没有成功...我获取了我的城市的天气预报,它是以Json格式提供的,我需要将该Json数据解析成Java对象。

Json数据如下:

{"city":
 {"city_code":"ATAT10678",
  "name":"Wien",
  "url":"oesterreich/wien/ATAT10678.html",
  "credit":{"info":"In order to use the free weather data from wetter.com you HAVE TO display at least two out of three of the following possibilities: text, link, logo",
  "text":"Powered by wetter.com","link":"http://www.wetter.com",
  "logo":"Download at http://www.wetter.com/api/downloads/#logos"},
  "forecast":{
   "2014-08-24":{
    "w":"1",
    "tx":"20",
    "pc":"30",
    "06:00":{
     "w":"2",
     "tx":"16",
     "pc":"30",
     "tn":"15",
     "p":"5",
     "dhl":"2014-08-24 06:00",
     "ws":"19",
     "w_txt":"wolkig"},
    "11:00":{
     "w":"2",
     "tx":"18",
     "pc":"30",
     "tn":"16",
     "p":"6",
     "dhl":"2014-08-24 11:00",
     "ws":"20",
     "w_txt":"wolkig"},
    "17:00":{
     "w":"1",
     "tx":"20",
     "pc":"20",
     "tn":"16",
     "p":"6",
     "dhl":"2014-08-24 17:00",
     "ws":"12",
     "w_txt":"leicht bewölkt"},
    "23:00":{
     "w":"1",
     "tx":"16",
     "pc":"10",
     "tn":"13",
     "p":"6",
     "dhl":"2014-08-24 23:00",
     "ws":"7",
     "w_txt":"leicht bewölkt"},
    "tn":"15",
    "p":"24",
    "dhl":"2014-08-24 06:00",
    "ws":"14",
    "w_txt":"leicht bewölkt"},
   "2014-08-25":{"w":"2","tx":"22","pc":"30","06:00":{"w":"2","tx":"17","pc":"20","tn":"12","p":"5","dhl":"2014-08-25 06:00","ws":"5","w_txt":"wolkig"},"11:00":{"w":"2","tx":"21","pc":"30","tn":"17","p":"6","dhl":"2014-08-25 11:00","ws":"10","w_txt":"wolkig"},"17:00":{"w":"2","tx":"22","pc":"30","tn":"18","p":"6","dhl":"2014-08-25 17:00","ws":"11","w_txt":"wolkig"},"23:00":{"w":"3","tx":"18","pc":"30","tn":"16","p":"6","dhl":"2014-08-25 23:00","ws":"6","w_txt":"bedeckt"},"tn":"12","p":"24","dhl":"2014-08-25 06:00","ws":"8","w_txt":"wolkig"},"2014-08-26":{"w":"3","tx":"22","pc":"75","06:00":{"w":"3","tx":"17","pc":"75","tn":"15","p":"5","dhl":"2014-08-26 06:00","ws":"6","w_txt":"bedeckt"},"11:00":{"w":"61","tx":"21","pc":"75","tn":"17","p":"6","dhl":"2014-08-26 11:00","ws":"9","w_txt":"leichter Regen"},"17:00":{"w":"61","tx":"22","pc":"75","tn":"18","p":"6","dhl":"2014-08-26 17:00","ws":"9","w_txt":"leichter Regen"},"23:00":{"w":"3","tx":"18","pc":"75","tn":"17","p":"6","dhl":"2014-08-26 23:00","ws":"9","w_txt":"bedeckt"},"tn":"15","p":"24","dhl":"2014-08-26 06:00","ws":"8","w_txt":"bedeckt"}}}}

我不知道如何将这个解析为对象。

非常感谢您的建议!

这是我的第一次尝试..

        Gson gson = new Gson();
        JsonObject jsonObj = gson.fromJson(br, JsonObject.class);
        Map<String, LinkedTreeMap> map = new HashMap<String, LinkedTreeMap>();
        map = (Map<String, LinkedTreeMap>) gson.fromJson(jsonObj.toString(), map.getClass());

        LinkedTreeMap<String, LinkedTreeMap> tmp = new LinkedTreeMap<>();
        tmp = map.get("city");

        for(Map.Entry<String, LinkedTreeMap> e : tmp.entrySet()) {
            System.out.println("k: " + e.getKey());
        }

        LinkedTreeMap<String, LinkedTreeMap> tmp1 = new LinkedTreeMap<>();
        tmp1 = tmp.get("forecast");

        for(Map.Entry<String, LinkedTreeMap> e : tmp1.entrySet()) {
            System.out.println("k: " + e.getKey());
            LinkedTreeMap<String, LinkedTreeMap> values = e.getValue();
            for(Map.Entry<String, LinkedTreeMap> v : values.entrySet()) {

                System.out.println("k: " + v.getKey() + " v: " + v.getValue());
            }

        }

并且一天内的输出结果:

k: city_code
k: name
k: url
k: credit
k: forecast
k: 2014-08-25
k: w v: 2
k: tx v: 23
k: pc v: 90
k: 06:00 v: {w=2, tx=17, pc=20, tn=13, p=5, dhl=2014-08-25 06:00, ws=5, w_txt=wolkig}
k: 11:00 v: {w=2, tx=21, pc=20, tn=17, p=6, dhl=2014-08-25 11:00, ws=9, w_txt=wolkig}
k: 17:00 v: {w=2, tx=23, pc=30, tn=17, p=6, dhl=2014-08-25 17:00, ws=11, w_txt=wolkig}
k: 23:00 v: {w=3, tx=17, pc=90, tn=16, p=6, dhl=2014-08-25 23:00, ws=6, w_txt=bedeckt}
k: tn v: 13
k: p v: 24
k: dhl v: 2014-08-25 06:00
k: ws v: 8
k: w_txt v: wolkig

到目前为止一切都很好,但我该如何获取06:00、11:00、17:00和23:00(因为时间可能会改变,所以这是通用的),因为这些是我需要的信息?
非常感谢,祝好! typhon

1
你现在尝试了什么?看看谷歌的GSOn库。https://code.google.com/p/google-gson/ - Adi
使用Gson解析,但我无法访问预测中的动态属性“2014-08-24”。 - typhon
我已经在这里回答了解决方案 https://dev59.com/mXE85IYBdhLWcg3wbS_1#15943171 - Tito
5个回答

4

以下是使用 GSON 的示例

import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
public class CodeChefTest1 {
    public static String json = "{\"balance\": 1000.21, \"num\":100, \"is_vip\":true, \"name\":\"foo\"}";
    public static void main(String[] args) {
        JsonElement ele = new JsonParser().parse(json);
        for(java.util.Map.Entry<String, JsonElement> entr : ele.getAsJsonObject().entrySet()){
            System.out.println(entr.getKey());
            System.out.println(entr.getValue());
        }
    }
}

您可以使用上述方法,并通过检查JSONElement(例如isJSONArray(),isJSONObject(),isJSONPrimitive()等)在循环中运行它,并使用相同的策略执行适当的重新解析。

上述代码只是遍历json字符串并打印所有键值对。您也可以对json字符串的日期部分执行相同的操作。


我已经尝试过了,但是由于它是变量,所以我无法访问预测中的属性“2014-08-24”。 - typhon

2
我个人推荐使用jackson。使用jackson,您可以将JSON字符串转换为POJO(Java bean)。 https://github.com/FasterXML/jackson 这个库是免费的,快速且易于使用。
由于您拥有日期和时间作为属性名称,因此我认为您对象的至少部分应该是JAVA映射,正如Amaynut建议的那样。

1
您可以使用谷歌的库Gson。以下是将JSON对象转换为Java类型Map的示例:
 Gson gson=new Gson(); 
String json="{\"k1\":\"v1\",\"k2\":\"v2\"}";
Map<String,String> map=new HashMap<String,String>();
map=(Map<String,String>) gson.fromJson(json, map.getClass());

尝试使用Gson库的另一种解决方案如下:

Gson gson = new Gson();
String json="{\"k1\":\"v1\",\"k2\":\"v2\"}";
LinkedTreeMap result = gson.fromJson(json, LinkedTreeMap.class);

你需要导入这两个类:

import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;

您可以查看关于相同主题的帖子: 如何使用Gson将JSON转换为HashMap?

我尝试了你的建议: Gson gson = new Gson(); JsonObject jsonObj = gson.fromJson(br, JsonObject.class); Map<String, String> map = new HashMap<String, String>(); map = (Map<String, String>) gson.fromJson(jsonObj.toString(), map.getClass());for(Map.Entry e : map.entrySet()) { System.out.println("k: " + e.getKey() + " v: " + e.getValue()); }但是我得到了一个java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap无法转换为java.lang.String? - typhon
在你的情况下,我认为你需要使用 Map<String, Object> 而不是 **Map<String, String>**。尝试一下并告诉我们是否有效。 - Amaynut

1

0

这是第一个可用的代码..(快速而简单)..

感谢Sumeet Sharma!也许有人有更好的解决方案...

    public void updateWeather() {
    forecasts = new ArrayList<>();
    try  {

        URL url = new URL(createURL());
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setDoOutput(true);

        OutputStream os = conn.getOutputStream();
        os.flush();

        if (conn.getResponseCode() != 200) {
            throw new RuntimeException("Failed : HTTP error code : "
                    + conn.getResponseCode());
        }

        BufferedReader br = new BufferedReader(new InputStreamReader(
                (conn.getInputStream())));

        Gson gson = new Gson();
        JsonObject jsonObj = gson.fromJson(br, JsonObject.class);

        JsonElement element = jsonObj.get("city");
        jsonObj = gson.fromJson(element.getAsJsonObject(), JsonObject.class);
        element = jsonObj.get("forecast");

        for (Map.Entry<String, JsonElement> entr : element.getAsJsonObject().entrySet()) {
            JsonElement element1 = entr.getValue().getAsJsonObject();
            for (Map.Entry<String, JsonElement> entr1 : element1.getAsJsonObject().entrySet()) {
                if (entr1.getValue().isJsonObject()) {
                    JsonElement element2 = entr1.getValue().getAsJsonObject();
                    Forecast forecast = new Forecast();
                    for (Map.Entry<String, JsonElement> entr2 : element2.getAsJsonObject().entrySet()) {
                        switch (entr2.getKey()) {
                            case "w":
                                forecast.setW(entr2.getValue().getAsString());
                                break;
                            case "tx":
                                forecast.setTx(entr2.getValue().getAsString());
                                break;
                            case "pc":
                                forecast.setPc(entr2.getValue().getAsString());
                                break;
                            case "tn":
                                forecast.setTn(entr2.getValue().getAsString());
                                break;
                            case "p":
                                forecast.setP(entr2.getValue().getAsString());
                                break;
                            case "dhl":
                                forecast.setDhl(entr2.getValue().getAsString());
                                break;
                            case "ws":
                                forecast.setWs(entr2.getValue().getAsString());
                                break;
                            case "w_txt":
                                forecast.setW_txt(entr2.getValue().getAsString());
                                break;
                        }
                    }
                    forecasts.add(forecast);
                }
            }
        }
        conn.disconnect();

    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    for(Forecast f : forecasts)
        System.out.println(f);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接