Today I encountered an API which sometimes sends back numbers as strings.

Example response:

{
    "age": "30"
}

That’s annoying, because I wanted my struct in Go to be like this:

type Person struct {
    Age int `json:"age"`
}

I learned that json struct tags have a string option meant for dealing with exactly this sort of problem:

The “string” option signals that a field is stored as JSON inside a JSON-encoded string. It applies only to fields of string, floating point, integer, or boolean types. This extra level of encoding is sometimes used when communicating with JavaScript programs:

Changing my struct to this worked great!

type Person struct {
    Age int `json:"age,string"`
}

Test program:

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Age int `json:"age,string"`
}

func main() {
    // Test 1
    p1 := Person{Age: 30}
    b1, _ := json.Marshal(p1)
    fmt.Println("Test 1:", string(b1))

    // Test 2
    s2 := `{"age":"30zz"}`
    var p2 Person
    _ = json.Unmarshal([]byte(s2), &p2)
    fmt.Println("Test 2:", p2)

    // Test 3
    s3 := `{"age":30}`
    var p3 Person
    if err := json.Unmarshal([]byte(s3), &p3); err != nil {
        fmt.Println("Test 3:", err)
    }
    fmt.Println("Test 3:", p3)
}

Output:

Test 1: {"age":"30"}
Test 2: {0}
Test 3: json: invalid use of ,string struct tag, trying to unmarshal unquoted value into int
Test 3: {0}