itchyny / gojq

Pure Go implementation of jq
MIT License
3.29k stars 118 forks source link

Support 1.23 iterator #262

Open amikai opened 3 months ago

amikai commented 3 months ago

Hi @itchyny,

The goquery package itself has already implemented the Iter interface. Have you considered supporting the 1.23 iterator, allowing users to directly use for-range on it?

goquery has already implemented its own Iter. Directly switching to iter.Seq or iter.Seq2 in version 1.23 is not practical. Therefore, my idea is to implement an adapter to convert it to iter.Seq or iter.Seq2.

Here is my rough idea.

package gojq

func ToSeq2(it Iter) iter.Seq2[any, error] {
    return func(yield func(x any, err error) bool) {
        for {
            v, ok := it.Next()
            if !ok {
                break
            }
            if err, ok := v.(error); ok {
                if !yield(nil, err) {
                    break
                }
            } else {
                if !yield(v, nil) {
                    break
                }
            }
        }
    }
}

The client will use it like this. Here is the code from the readme example, modified to use ToSeq2:

query, err := gojq.Parse(".foo | ..")
if err != nil {
    log.Fatalln(err)
}
input := map[string]any{"foo": []any{1, 2, 3}}
for val, err := range gojq.ToSeq2(query.Run(input)) {
    if err != nil {
        if err, ok := err.(*gojq.HaltError); ok && err.Value() == nil {
            break
        }
        log.Fatalln(err)
    }
    fmt.Printf("%#v\n", val)
}
itchyny commented 3 months ago

Yes, this is on my todo list and I have a patch locally. I will gradually update the Go version carefully, while watching the reactions to the new features. Please wait.