user9946708
user9946708

Reputation:

How to treat different types in JSON response in golang or typed language in general

I am working on a project in golang and I need to work with JSON response. The thing is that a value in JSON coming from server can be something like

{person: "john"} 

or

{person: {name:"john"}} 

so to create a structure for capturing this I have a couple of options:

1) make person type as interface{}, but this will have redundant code later to work with the value

2) store values in new properties, like PersonAsString and PersonAsObject, this makes code bit more unpredictable as it meant to be used as a module for other developers

any other pros and cons for this? any other suggestions how to treat unknown type JSON fields?

Upvotes: 1

Views: 658

Answers (2)

KeKsBoTer
KeKsBoTer

Reputation: 192

Another option is to define a type with custom JSON marshal and unmarshal functions.

type Person string

func (p *Person) UnmarshalJSON(b []byte) error {
    if strings.HasPrefix(string(*p),"{"){
        value := map[string]string{}
        json.Unmarshal(b,&value)
        *p = Person(value["name"])
    }else{
        *p = Person(b)
    }
    return nil
}

func (p Person) MarshalJSON() ([]byte, error) {
    return []byte(p),nil
}


type PersonStruct struct{
    Person  Person `json:"person"`
}

func main(){
    one := `{"person": "john"}`
    two := `{"person": {name:"john"}}`
    result := PersonStruct{}
    json.Unmarshal([]byte(one),&result)
    fmt.Println(result)
    json.Unmarshal([]byte(two),&result)
    fmt.Println(result)
}

Upvotes: 3

cn0047
cn0047

Reputation: 17091

In this case you have to use interface{}.
But with purpose to reduce complexity of your struct you can have one additional field like NameValue and fill this value after json.Unmarshal and assign value or from person either from person.name.
In your code you can loosely use NameValue which will always contain correct value.

Upvotes: 0

Related Questions