如何在Go语言中解析JSON数据并输出为清晰文本格式
嘿,这个需求实现起来超简单的!我给你两种实用的方法,你可以根据自己的场景来选:
方法一:定义结构体解析后格式化输出(推荐,类型安全)
这种方法是先把ipinfo.io返回的JSON结构映射成Go的结构体,然后直接提取字段拼接成你要的文本格式,优点是类型安全,不容易出错,适合需要固定输出字段的场景。
首先定义和接口返回对应的结构体:
type IPInfo struct { IP string `json:"ip"` City string `json:"city"` Region string `json:"region"` Country string `json:"country"` Loc string `json:"loc"` // 经纬度信息 Org string `json:"org"` // 运营商/机构信息 Postal string `json:"postal"` Timezone string `json:"timezone"` }
然后修改你的iplocation函数,解析JSON后格式化输出:
import ( "encoding/json" "fmt" "net/http" ) func ipLocation(ip string) error { // 构造请求URL reqURL := fmt.Sprintf("https://ipinfo.io/%s/json", ip) resp, err := http.Get(reqURL) if err != nil { return fmt.Errorf("请求ipinfo接口失败: %w", err) } defer resp.Body.Close() // 解析JSON到结构体 var ipInfo IPInfo if err := json.NewDecoder(resp.Body).Decode(&ipInfo); err != nil { return fmt.Errorf("解析JSON失败: %w", err) } // 按照你想要的格式拼接输出文本 result := fmt.Sprintf( "ip: %s, city: %s, region: %s, country: %s, location: %s, org: %s, postal: %s, timezone: %s", ipInfo.IP, ipInfo.City, ipInfo.Region, ipInfo.Country, ipInfo.Loc, ipInfo.Org, ipInfo.Postal, ipInfo.Timezone, ) fmt.Println(result) return nil }
如果担心某些字段为空(比如部分IP可能没有postal信息),还可以加个简单的空值处理,比如:
// 处理空字段,替换成"未知" city := ipInfo.City if city == "" { city = "未知" } // 然后在Sprintf里用city变量代替ipInfo.City
方法二:用Map解析(灵活,无需定义结构体)
如果你不想提前定义结构体,也可以直接把JSON解析成map[string]interface{},然后提取对应字段输出。这种方法更灵活,但要注意类型断言,避免panic:
func ipLocation(ip string) error { reqURL := fmt.Sprintf("https://ipinfo.io/%s/json", ip) resp, err := http.Get(reqURL) if err != nil { return fmt.Errorf("请求接口失败: %w", err) } defer resp.Body.Close() var ipInfo map[string]interface{} if err := json.NewDecoder(resp.Body).Decode(&ipInfo); err != nil { return fmt.Errorf("解析JSON失败: %w", err) } // 提取字段时做类型断言,避免类型不匹配panic ipStr, _ := ipInfo["ip"].(string) cityStr, _ := ipInfo["city"].(string) regionStr, _ := ipInfo["region"].(string) countryStr, _ := ipInfo["country"].(string) result := fmt.Sprintf("ip: %s, city: %s, region: %s, country: %s", ipStr, cityStr, regionStr, countryStr) fmt.Println(result) return nil }
这里用_忽略了断言失败的错误,如果字段不存在或者类型不对,对应的变量会是空字符串,你也可以根据需要添加错误处理逻辑。
总的来说,第一种方法更推荐,因为类型安全,代码可读性也更高,适合大多数场景~
内容的提问来源于stack exchange,提问作者Inzamam Raja
相关产品推荐
相关产品推荐

