From c90450abc923c932d4b13922b63b220fe1429f4c Mon Sep 17 00:00:00 2001 From: Vincent Boutour Date: Fri, 29 Mar 2024 14:37:40 +0100 Subject: [PATCH] refactor(httpjson): Refactor stream parser Signed-off-by: Vincent Boutour --- pkg/httpjson/json.go | 53 ++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/pkg/httpjson/json.go b/pkg/httpjson/json.go index 66ff026d..32ac439a 100644 --- a/pkg/httpjson/json.go +++ b/pkg/httpjson/json.go @@ -95,16 +95,18 @@ func Stream[T any](stream io.Reader, output chan<- T, key string, closeChan bool decoder := json.NewDecoder(stream) if len(key) > 0 { - if err := moveDecoderToKey(decoder, key); err != nil { - return err + if err := moveToKey(decoder, key); err != nil { + return fmt.Errorf("move to key: %w", err) } } var obj T + for decoder.More() { if err := decoder.Decode(&obj); err != nil { return fmt.Errorf("decode stream: %w", err) } + output <- obj } @@ -117,33 +119,42 @@ func Stream[T any](stream io.Reader, output chan<- T, key string, closeChan bool return nil } -func moveDecoderToKey(decoder *json.Decoder, key string) error { - var token json.Token +func moveToKey(decoder *json.Decoder, key string) error { + if key != "." { + if err := findStart(decoder, key); err != nil { + return fmt.Errorf("find start: %w", err) + } + } + + if _, err := decoder.Token(); err != nil { + return fmt.Errorf("read opening token: %w", err) + } + + return nil +} + +func findStart(decoder *json.Decoder, key string) error { var nested uint64 - var err error - if key != "." { - for { - token, err = decoder.Token() - if err != nil { - return fmt.Errorf("decode token: %w", err) - } + for { + token, err := decoder.Token() + if err != nil { + return fmt.Errorf("decode token: %w", err) + } - if nested == 1 && strings.EqualFold(fmt.Sprintf("%s", token), key) { - break + switch tokenType := token.(type) { + case string: + if nested == 1 && strings.EqualFold(tokenType, key) { + return nil } - if strToken := fmt.Sprintf("%s", token); strToken == "{" { + case json.Delim: + switch tokenType { + case '{': nested++ - } else if strToken == "}" { + case '}': nested-- } } } - - if _, err = decoder.Token(); err != nil { - return fmt.Errorf("read opening token: %w", err) - } - - return nil }