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

Decode fails when input stream ends with a newline #698

Open lev112 opened 4 months ago

lev112 commented 4 months ago

when using the Encode of the standard package, it adds a \n after every object, but when json-iterator gets it as an input, it fails, see code for an example:

import (
    "bytes"
    "encoding/json"
    "io"
    "testing"

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

    "github.com/stretchr/testify/require"
)

func TestJsonIterator(t *testing.T) {
    // encode jsons using the built in package
    buf := new(bytes.Buffer)
    enc := json.NewEncoder(buf)
    err := enc.Encode(map[string]string{"key": "value"})
    require.NoError(t, err)
    err = enc.Encode(map[string]string{"key2": "value2"})
    require.NoError(t, err)

    // after the last value, \n is added
    var nl byte = '\n'
    require.Equal(t, nl, buf.Bytes()[buf.Len()-1])

    // the build in package can decode the values as expected
    reader1 := bytes.NewReader(buf.Bytes())
    dec1 := json.NewDecoder(reader1)

    var res map[string]string

    err = dec1.Decode(&res)
    require.NoError(t, err)
    require.Equal(t, map[string]string{"key": "value"}, res)

    res = nil
    err = dec1.Decode(&res)
    require.NoError(t, err)
    require.Equal(t, map[string]string{"key2": "value2"}, res)

    res = nil
    err = dec1.Decode(&res)
    require.Equal(t, io.EOF, err)

    reader2 := bytes.NewReader(buf.Bytes())
    // if the last \n is removed from the input, everything works as expected
    //reader2 := bytes.NewReader(buf.Bytes()[:buf.Len()-1])

    dec2 := jsoniter.ConfigDefault.NewDecoder(reader2)

    err = dec2.Decode(&res)
    require.NoError(t, err)
    require.Equal(t, map[string]string{"key": "value"}, res)

    res = nil
    err = dec2.Decode(&res)
    require.NoError(t, err)
    require.Equal(t, map[string]string{"key2": "value2"}, res)

    res = nil
    err = dec2.Decode(&res)
    // this check fails
    // the actual error is:
    // &errors.errorString{s:"ReadMapCB: expect { or n, but found \x00, error found in #10 byte of ...|:\"value2\"}\n|..., bigger context ...|{\"key\":\"value\"}\n{\"key2\":\"value2\"}\n|..."}
    require.Equal(t, io.EOF, err)
}
egsam98 commented 2 months ago

Same problem here. Unfortunately, this library seems to be abandoned :c