francoispqt / gojay

high performance JSON encoder/decoder with stream API for Golang
MIT License
2.11k stars 112 forks source link

What is the suggested way to decode into an array? #94

Closed verytable closed 5 years ago

verytable commented 5 years ago

There is a section in docs https://github.com/francoispqt/gojay#arrays-slices-and-channels describing how to decode JSON object to a slice, an array or a channel with examples for a slice and a channel.

User has to implement UnmarshalerJSONArray interface consisting of a single function UnmarshalJSONArray which is called on each element of a collection.

Provided example for a slice (where user can simply append each new element to receiver):

type testSlice []string
// implement UnmarshalerJSONArray
func (t *testStringArr) UnmarshalJSONArray(dec *gojay.Decoder) error {
    str := ""
    if err := dec.String(&str); err != nil {
        return err
    }
    *t = append(*t, str)
    return nil
}

The problem with an array is that there is no (or is there?) way to get current index of unmarshalled array element.

Of course user can maintain this index himself:

type testArray struct {
    arr       [3]string
    decodeIdx int
}

func (a *testArray) UnmarshalJSONArray(dec *gojay.Decoder) error {
    str := ""
    if err := dec.String(&str); err != nil {
        return err
    }
    a.arr[a.decodeIdx] = str
    a.decodeIdx++
    // handle overflow
    return nil
}

Is this the suggested way or i'm missing more elegant/concise/idiomatic solution?

francoispqt commented 5 years ago

Hi,

This is probably the best way, but it makes me think we could add a Index() method on the decoder which would return the current index of the array being decoded.

With such solution, you'd do it this way:

type testArray  [3]string

func (a *testArray) UnmarshalJSONArray(dec *gojay.Decoder) error {
    var str string
    if err := dec.String(&str); err != nil {
        return err
    }
    a.arr[dec.Index()] = str
    return nil
}

I can create a milestone but I won't be able to do it before 2 weeks. You're welcome to submit a PR.

Let me know