2017-12-20 16 views
2

필드를 공유하는 구조가 다르므로 JSON 파일을 Go에서 해당 구조로 디코딩해야합니다.Golang이 우아하게 JSON으로 다른 구조를 디코드합니다.

는 예 :

type Dog struct { 
    AnimalType string //will always be "dog" 
    BarkLoudnessLevel int 
} 

type Cat struct { 
    AnimalType string //will always be "cat" 
    SleepsAtNight bool 
} 

내가 JSON 문자열로 이러한 구조 중 하나를 수신하고있는 경우, 어떤 일이 적절한 구조로 구문 분석의 가장 우아한 방법이 있을까요?

+0

이동 웹 사이트 (https://golang.org/pkg/encoding/json/)에서 제공되는 예제를 살펴 보겠습니다. "Example (CustomMarshalJSON)"을 참조하십시오. –

+0

"예제 (Unmarshal) "['json.RawMessage' 유형] (https://golang.org/pkg/encoding/json/#RawMessage)을 참조하십시오. – maerics

답변

5

이렇게하려면 두 가지 방법이 있지만 가장 쉬운 방법은 페이로드를 두 번 deserialize하고 페이로드의 "AnimalType"특성을 기반으로 조건 분기를하는 것입니다. 여기에 중간 역 직렬화 모델을 사용하여 간단한 예입니다

package main 

import (
    "fmt" 
    "encoding/json" 
) 

type Dog struct { 
    AnimalType string //will always be "dog" 
    BarkLoudnessLevel int 
} 

type Cat struct { 
    AnimalType string //will always be "cat" 
    SleepsAtNight bool 
} 

var (
    payloadOne = `{"AnimalType":"dog","BarkLoudnessLevel":1}` 
    payloadTwo = `{"AnimalType":"cat","SleepsAtNight":false}` 
) 

func main() { 
    parseAnimal(payloadOne) 
    parseAnimal(payloadTwo) 
} 

func parseAnimal(payload string) { 
    animal := struct{ 
    AnimalType string 
    }{} 
    if err := json.Unmarshal([]byte(payload), &animal); err != nil { 
    panic(err) 
    } 
    switch animal.AnimalType { 
    case "dog": 
    dog := Dog{} 
    if err := json.Unmarshal([]byte(payload), &dog); err != nil { 
     panic(err) 
    } 
    fmt.Printf("Got a dog: %v\n", dog) 
    case "cat": 
    cat := Cat{} 
    if err := json.Unmarshal([]byte(payload), &cat); err != nil { 
     panic(err) 
    } 
    fmt.Printf("Got a cat: %v\n", cat) 
    default: 
    fmt.Println("Unknown animal") 
    } 
} 

행동 here에서를 참조하십시오.


IMO이 예상되는 JSON 페이로드를 수정 필요하지만이 부모 구조로 페이로드에 대한 "메타 데이터"이동 접근하는 더 좋은 방법. 따라서, 예를 들어, 당신처럼 보였다 페이로드와 함께 작업하는 경우 :

{"AnimalType":"dog", "Animal":{"BarkLoudnessLevel": 1}} 

이 그럼 당신은 부분적으로 구조를 분석 할 json.RawMessage 같은 것을 사용할 수 있습니다 및 다음 필요에 따라 조건부로 나머지 구문 분석 (오히려 모든 것을 분석하는 것보다 두 배) - 또한 구조 속성을 더 잘 분리합니다. 다음과 같은 예가 있습니다.

package main 

import (
    "encoding/json" 
    "fmt" 
) 

type Animal struct { 
    AnimalType string 
    Animal  json.RawMessage 
} 

type Dog struct { 
    BarkLoudnessLevel int 
} 

type Cat struct { 
    SleepsAtNight bool 
} 

var (
    payloadOne = `{"AnimalType":"dog", "Animal":{"BarkLoudnessLevel": 1}}` 
    payloadTwo = `{"AnimalType":"cat", "Animal":{"SleepsAtNight": false}}` 
) 

func main() { 
    parseAnimal(payloadOne) 
    parseAnimal(payloadTwo) 
} 

func parseAnimal(payload string) { 
    animal := &Animal{} 
    if err := json.Unmarshal([]byte(payload), &animal); err != nil { 
     panic(err) 
    } 
    switch animal.AnimalType { 
    case "dog": 
     dog := Dog{} 
     if err := json.Unmarshal(animal.Animal, &dog); err != nil { 
      panic(err) 
     } 
     fmt.Printf("Got a dog: %v\n", dog) 
    case "cat": 
     cat := Cat{} 
     if err := json.Unmarshal(animal.Animal, &cat); err != nil { 
      panic(err) 
     } 
     fmt.Printf("Got a cat: %v\n", cat) 
    default: 
     fmt.Println("Unknown animal") 
    } 
} 

그리고 동작이 here입니다.