Go解析json字符串中多种类型混合的list
2015-10-13 1 阅读
Go
我每天似乎都要写代码来解析json字符串,然后总会遇到一些让人不太舒服的Json数据。其中多种类型混合的Json数据会让人很头疼。
假如给定一个json对象列表的不同类型(假设人物和地点)。你想将它分解成两个列表。一个列表的所有人,和所有地方的列表。
我们先看下Json数据:
{ "things": [ { "name": "Alice", "age": 37 }, { "city": "Ipoh", "country": "Malaysia" }, { "name": "Bob", "age": 36 }, { "city": "Northampton", "country": "England" } ] }我们需要自己写自定义一个函数:
func solution(jsonString []byte) ([]Person []Place) {}还有Struct
type Person struct { Name string Age int } type Place struct { City string Country string } 方法A: map and type assert func solutionA(jsonStr []byte) ([]Person, []Place) { persons := []Person{} places := []Place{} var data map[string][]map[string]interface{} err := json.Unmarshal(jsonStr, &data) if err != nil { fmt.Println(err) return persons, places } for i := range data["things"] { item := data["things"][i] if item["name"] != nil { persons = addPerson(persons, item) } else { places = addPlace(places, item) } } return persons, places } func addPerson(persons []Person, item map[string]interface{}) []Person { name, _ := item["name"].(string) age, _ := item["age"].(int) person := Person{name, age} persons = append(persons, person) return persons } func addPlace(places []Place, item map[string]interface{}) []Place { city, _ := item["city"].(string) country, _ := item["city"].(string) place := Place{city, country} places = append(places, place) return places } 方法B: Mixed Type struct type Mixed struct { Name string `json:"name"` Age int `json:"age"` City string `json:"city"` Country string `json:"country"` } func solutionB(jsonStr []byte) ([]Person, []Place) { persons := []Person{} places := []Place{} var data map[string][]Mixed err := json.Unmarshal(jsonStr, &data) if err != nil { fmt.Println(err) return persons, places } for i := range data["things"] { item := data["things"][i] if item.Name != "" { persons = append(persons, Person{item.Name, item.Age}) } else { places = append(places, Place{item.City, item.Country}) } } return persons, places } 方法C: json.RawMessage func solutionC(jsonStr []byte) ([]Person, []Place) { people := []Person{} places := []Place{} var data map[string][]json.RawMessage err := json.Unmarshal(jsonStr, &data) if err != nil { fmt.Println(err) return people, places } for _, thing := range data["things"] { people = addPersonC(thing, people) places = addPlaceC(thing, places) } return people, places } func addPersonC(thing json.RawMessage, people []Person) []Person { person := Person{} if err := json.Unmarshal(thing, &person); err != nil { fmt.Println(err) } else { if person != *new(Person) { people = append(people, person) } } return people } func addPlaceC(thing json.RawMessage, places []Place) []Place { place := Place{} if err := json.Unmarshal(thing, &place); err != nil { fmt.Println(err) } else { if place != *new(Place) { places = append(places, place) } } return places }我们可以在main方法中测试一下:
package main import ( "encoding/json" "fmt" ) var jsonStr = []byte(` { "things": [ { "name": "Alice", "age": 37 }, { "city": "Ipoh", "country": "Malaysia" }, { "name": "Bob", "age": 36 }, { "city": "Northampton", "country": "England" } ] }`) func main() { personsA, placesA := solutionA(jsonStr) fmt.Printf("%d %d\n", len(personsA), len(placesA)) personsB, placesB := solutionB(jsonStr) fmt.Printf("%d %d\n", len(personsB), len(placesB)) personsC, placesC := solutionC(jsonStr) fmt.Printf("%d %d\n", len(personsC), len(placesC)) } //Common to both solutions type Person struct { Name string Age int } type Place struct { City string Country string } //Solution A //Unmarshal into a map //Type assert when we need it func solutionA(jsonStr []byte) ([]Person, []Place) { persons := []Person{} places := []Place{} var data map[string][]map[string]interface{} err := json.Unmarshal(jsonStr, &data) if err != nil { fmt.Println(err) return persons, places } for i := range data["things"] { item := data["things"][i] if item["name"] != nil { persons = addPerson(persons, item) } else { places = addPlace(places, item) } } return persons, places } func addPerson(persons []Person, item map[string]interface{}) []Person { name, _ := item["name"].(string) age, _ := item["age"].(int) person := Person{name, age} persons = append(persons, person) return persons } func addPlace(places []Place, item map[string]interface{}) []Place { city, _ := item["city"].(string) country, _ := item["city"].(string) place := Place{city, country} places = append(places, place) return places } //SolutionB type Mixed struct { Name string `json:"name"` Age int `json:"age"` City string `json:"city"` Country string `json:"country"` } func solutionB(jsonStr []byte) ([]Person, []Place) { persons := []Person{} places := []Place{} var data map[string][]Mixed err := json.Unmarshal(jsonStr, &data) if err != nil { fmt.Println(err) return persons, places } for i := range data["things"] { item := data["things"][i] if item.Name != "" { persons = append(persons, Person{item.Name, item.Age}) } else { places = append(places, Place{item.City, item.Country}) } } return persons, places } //SolutionC func solutionC(jsonStr []byte) ([]Person, []Place) { people := []Person{} places := []Place{} var data map[string][]json.RawMessage err := json.Unmarshal(jsonStr, &data) if err != nil { fmt.Println(err) return people, places } for _, thing := range data["things"] { people = addPersonC(thing, people) places = addPlaceC(thing, places) } return people, places } func addPersonC(thing json.RawMessage, people []Person) []Person { person := Person{} if err := json.Unmarshal(thing, &person); err != nil { fmt.Println(err) } else { if person != *new(Person) { people = append(people, person) } } return people } func addPlaceC(thing json.RawMessage, places []Place) []Place { place := Place{} if err := json.Unmarshal(thing, &place); err != nil { fmt.Println(err) } else { if place != *new(Place) { places = append(places, place) } } return places }Go解析json字符串中多种类型混合的list
Go
作者:
Give Me Freedom,Give Me Fire ,Give Me Reason .Take Me Higher
原文地址:Go解析json字符串中多种类型混合的list, 感谢原作者分享。
→nginx日志格式的自定义和配置 ←YahooNewsOnboarding 仿雅虎新闻引导页面效果
发表评论