Swift中使用Decodable解析同一JSON内不同容器的数据
没问题!复用同一个Weather结构体来解析不同位置的JSON数据完全可行,核心就是针对不同的JSON路径做数据提取,然后映射到同一个结构体上。我给你分几种常见语言的场景来举例,你可以对应自己用的语言参考:
解决方案:复用Weather结构体解析不同JSON路径
核心思路
不管JSON数据在哪个容器里,只要字段结构匹配,就能用同一个结构体来解析。关键是定位到目标数据所在的JSON节点,再把节点数据反序列化到Weather结构体即可。
示例代码(Go语言)
假设你的JSON结构长这样:
{ "currently": { "temp": 22.5, "humidity": 0.6, "summary": "Partly Cloudy" }, "daily": { "data": [ { "temp": 25.0, "humidity": 0.5, "summary": "Sunny" }, { "temp": 23.0, "humidity": 0.7, "summary": "Cloudy" } ] } }
首先定义你的Weather结构体(和你现有解析currently的一样):
type Weather struct { Temp float64 `json:"temp"` Humidity float64 `json:"humidity"` Summary string `json:"summary"` }
然后解析不同位置的数据:
package main import ( "encoding/json" "fmt" ) // 上面的Weather结构体定义在这里 func main() { jsonData := []byte(`{"currently": {"temp":22.5,"humidity":0.6,"summary":"Partly Cloudy"},"daily":{"data":[{"temp":25.0,"humidity":0.5,"summary":"Sunny"},{"temp":23.0,"humidity":0.7,"summary":"Cloudy"}]}}`) // 方式1:先解析整个JSON到临时结构,定位目标节点 var rawData map[string]interface{} if err := json.Unmarshal(jsonData, &rawData); err != nil { panic(err) } // 解析currently容器的Weather对象 currentlyBytes, _ := json.Marshal(rawData["currently"]) var currentWeather Weather json.Unmarshal(currentlyBytes, ¤tWeather) fmt.Println("当前天气:", currentWeather) // 解析daily->data里的多个Weather对象 dailyData := rawData["daily"].(map[string]interface{})["data"].([]interface{}) var dailyWeathers []Weather for _, item := range dailyData { itemBytes, _ := json.Marshal(item) var w Weather json.Unmarshal(itemBytes, &w) dailyWeathers = append(dailyWeathers, w) } fmt.Println("每日天气:", dailyWeathers) // 方式2:定义顶层结构体,一次性解析更优雅 type WeatherResponse struct { Currently Weather `json:"currently"` Daily DailyData `json:"daily"` } type DailyData struct { Data []Weather `json:"data"` } var resp WeatherResponse json.Unmarshal(jsonData, &resp) fmt.Println("优雅版当前天气:", resp.Currently) fmt.Println("优雅版每日天气:", resp.Daily.Data) }
示例代码(Python语言)
用dataclasses和json模块实现,代码更简洁:
import json from dataclasses import dataclass from typing import List @dataclass class Weather: temp: float humidity: float summary: str json_str = '''{"currently": {"temp":22.5,"humidity":0.6,"summary":"Partly Cloudy"},"daily":{"data":[{"temp":25.0,"humidity":0.5,"summary":"Sunny"},{"temp":23.0,"humidity":0.7,"summary":"Cloudy"}]}}''' data = json.loads(json_str) # 解析currently的Weather对象 current_weather = Weather(**data["currently"]) print("当前天气:", current_weather) # 解析daily->data的多个Weather对象 daily_weathers = [Weather(**item) for item in data["daily"]["data"]] print("每日天气:", daily_weathers)
关键要点
- 确保
Weather结构体的字段和JSON中目标对象的字段完全匹配(包括键名、数据类型),如果键名不一致可以用结构体标签(比如Go的json:"xxx",Python可以自定义字段映射)。 - 不需要为不同位置的数据重新定义结构体,只要定位到对应的JSON节点,把节点数据反序列化到同一个
Weather结构体即可。 - 强类型语言推荐用顶层结构体的方式解析,代码更易维护;动态类型语言直接提取节点后映射即可。
内容的提问来源于stack exchange,提问作者Angus.M
相关产品推荐
相关产品推荐

