What could possibly go wrong with JSON parsing?

Nuances

Type 1: Specification vs Implementation

Source: http://seriot.ch/parsing_json.php

Type 2: Dynamically typed vs Statically typed languages

<?php$to_encode = 1;
$data = ['a' => $to_encode];
echo json_encode($data)."\n";
?>
package mainimport (
"bufio"
"encoding/json"
"fmt"
"os"
)
// "a" is a tag used to tell json package
// to look for "a" key in received JSON
type B struct {
A int `json:"a"`
}
func main() {
// read input from stdin
reader := bufio.NewReader(os.Stdin)
str, _ := reader.ReadString('\n')
// the json string
fmt.Print("json:", str)
b := B{}
err := json.Unmarshal([]byte(str), &b)
if err != nil {
fmt.Println("go: error occurred - ", err)
return
}
// decoded value
fmt.Printf("go: %+v", b)
fmt.Println()
}
> php encode.php | go run decode_copy.go
json: {“a”:1}
go: {A:1}
$to_encode = 1; //PHP// Go
type B struct {
A int `json:"a"`
}
// Bash outputjson: {“a”:1}go: {A:1}

Problem #1: representability of large numbers

$to_encode = 123; //PHP// Go
type B struct {
A int `json:"a"`
}
// Bash outputjson: {"a":123}go: {A:123}
$to_encode = 123123123123123123123; //PHP// Go
type B struct {
A int `json:"a"`
}
// Bash outputjson:{"a":1.2312312312312313e+20}go: error occurred - json: cannot unmarshal number 1.2312312312312313e+20 into Go struct field B.a of type int

Problem #2: numbers as strings

$to_encode = 3.141592653589793238462643383279; //PHP// Go
type B struct {
A float64 `json:"a"`
}
// Bash outputjson: {"a":3.141592653589793}go: {A:3.141592653589793}
$to_encode = "3.141592653589793238462643383279"; //PHP// Gotype B struct {
A float64 `json:"a"`
}
// Bash outputjson: {"a":"3.141592653589793238462643383279"}go: error occurred - json: cannot unmarshal string into Go struct field B.a of type float64
  1. One way to solve this would be to use the string tag which is used to indicate to the json package that the value would be found as a string in the received response.
$to_encode = "3.141592653589793238462643383279"; //PHP// Go
type B struct {
A float64 `json:"a,string"`
}
// Bash outputjson: {"a":"3.141592653589793238462643383279"}go: {A:3.141592653589793238462643383279}
$to_encode = 3.141592653589793238462643383279; //PHP// Gotype B struct {
A float64 `json:"a,string"`
}
// Bash outputjson: {"a":3.141592653589793}go: error occurred - json: invalid use of ,string struct tag, trying to unmarshal unquoted value into float64
<?php$to_encode = "3.141592653589793238462643383279";
$data = ['a' => $to_encode];
echo json_encode($data, JSON_NUMERIC_CHECK)."\n";
?>
$to_encode = "3.141592653589793238462643383279"; //PHP// Go
type B struct {
A float64 `json:"a"`
}
// Bash outputjson: {"a":3.141592653589793}go: {A:3.141592653589793}
$to_encode = "3.141592653589793238462643383279"; //PHP// Go
type B struct {
A json.Number `json:"a"`
}
// Bash outputjson: {"a":"3.141592653589793238462643383279"}go: {A:3.141592653589793238462643383279}

Problem #3: booleans as numbers/strings

$to_encode = True; //PHP// Go
type B struct {
A bool `json:"a"`
}
// Bash outputjson: {"a":true}go: {A:true}
$to_encode = 1; //PHP// Gotype B struct {
A bool `json:"a"`
}
// Bash outputjson: {"a":1}go: error occurred - json: cannot unmarshal number into Go struct field B.a of type bool
type jbool boolfunc (jb *jbool) UnmarshalJSON(b []byte) error {
var i interface{}
err := json.Unmarshal(b, &i)
if err != nil {
return err
}
switch v := i.(type) {
case bool:
*jb = jbool(v)
case string:
x, err := strconv.ParseBool(v)
if err != nil {
return err
}
*jb = jbool(x)
case float64:
*jb = v != 0
case int, int32, int64:
*jb = v == 1
default:
err = errors.New("bool could not be decoded into jbool")
}
return nil
}
$to_encode = 1; //PHP// Go
type B struct {
A jbool `json:"a"`
}
// Bash outputjson: {"a":1}go: {A:true}

Reference to other materials:

--

--

--

I code, among other things.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Taking SASS to the next level

Ansbile playbook Task 11.3

Python Harmonic Analysis Curving fitting for the Exported Time Series Data From Google Earth Engine

APIs: What got you here won’t get you there

The grid

8 Skills Every Programmer Needs to Get a Job Easily

Activate Your Data Streams Using RudderStack: A Use-Case with AWS Lambda and Amazon Kinesis

Elasticsearch Index Red / Yellow — Why?

Distributed Tracing of Spring boot microservices with zipkin part-2

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Yasoob Haider

Yasoob Haider

I code, among other things.

More from Medium

Exclusive with EarlyBirds Founder, Kris Poria

Exclusive with EarlyBirds Founder, Kris Poria

Live Music: A blatant money-grab

5 Thoughts on a Wild, Wacky, Weird, Wolves Win

Welcome to GEN2 Multiverse GnomieZ