json-iterator / go

A high-performance 100% compatible drop-in replacement of "encoding/json"
http://jsoniter.com/migrate-from-go-std.html
MIT License
13.33k stars 1.02k forks source link

Fix `,string` option applying to non applicable value / types #660

Open ngicks opened 1 year ago

ngicks commented 1 year ago

This is a PR that explores how to fix https://github.com/json-iterator/go/issues/657#issuecomment-1429702605.

The json:",string" option incorrectly quotes value even when it must not be applied.

If this patch is merged, it would not quote nil, or types other than string, boolean, numeric and pointer types that points to those. Also it would report error correctly.

package main

import (
    "encoding/json"
    "fmt"

    jsoniter "github.com/json-iterator/go"
)

type quote struct {
    S *string `json:",string"`
}

func main() {
    var (
        q   quote
        err error
    )
    for idx, str := range []string{
        `{}`,
        `{"S":"\"234\""}`,
        `{"S":"\"\""}`,
        `{"S":"\""}`,
        `{"S":"234"}`,
        `{"S":234"}`,
        `{"S":"234}`,
    } {
        fmt.Printf("case %d, %s\n", idx, str)
        err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal([]byte(str), &q)
        fmt.Printf("jsoniter err: %+v\n", err)
        err = json.Unmarshal([]byte(str), &q)
        fmt.Printf("json err: %+v\n", err)
        fmt.Println()
    }
}

/*
case 0, {}
jsoniter err: <nil>
json err: <nil>

case 1, {"S":"\"234\""}
jsoniter err: <nil>
json err: <nil>

case 2, {"S":"\"\""}
jsoniter err: <nil>
json err: <nil>

case 3, {"S":"\""}
jsoniter err: main.quote.S: stringModeStringDecoder: expect len(s) >= 2, but found ", error found in #9 byte of ...|{"S":"\""}|..., bigger context ...|{"S":"\""}|...
json err: json: invalid use of ,string struct tag, trying to unmarshal "\"" into string

case 4, {"S":"234"}
jsoniter err: main.quote.S: stringModeStringDecoder: expect ", but found 2, error found in #10 byte of ...|{"S":"234"}|..., bigger context ...|{"S":"234"}|...
json err: json: invalid use of ,string struct tag, trying to unmarshal "234" into string

case 5, {"S":234"}
jsoniter err: main.quote.S: ReadString: expects " or n, but found 2, error found in #6 byte of ...|{"S":234"}|..., bigger context ...|{"S":234"}|...
json err: invalid character '"' after object key:value pair

case 6, {"S":"234}
jsoniter err: main.quote.S: readStringSlowPath: unexpected end of input, error found in #10 byte of ...|{"S":"234}|..., bigger context ...|{"S":"234}|...
json err: unexpected end of JSON input
*/