From 7f2376a9047f01958a691e34d9fbb51f1fa146ba Mon Sep 17 00:00:00 2001 From: Leonid Nikitin Date: Sat, 14 Mar 2026 11:36:25 +0500 Subject: [PATCH] Add JSON lines parser implementation with IP extraction support --- parser/json_lines.go | 59 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 parser/json_lines.go diff --git a/parser/json_lines.go b/parser/json_lines.go new file mode 100644 index 0000000..c67f192 --- /dev/null +++ b/parser/json_lines.go @@ -0,0 +1,59 @@ +package parser + +import ( + "encoding/json" + "fmt" + "io" + "strings" +) + +type jsonLinesExtract func(item json.RawMessage) (string, error) + +type jsonLinesParser struct { + extract jsonLinesExtract +} + +func NewJsonLines(extract jsonLinesExtract) (Parser, error) { + if extract == nil { + return nil, fmt.Errorf("json lines extract is nil") + } + + return &jsonLinesParser{ + extract: extract, + }, nil +} + +func (p *jsonLinesParser) Parse(body io.Reader, validator IPValidator, limit uint) (IPs, error) { + decoder := json.NewDecoder(body) + ips := make(IPs, 0) + for { + var item json.RawMessage + if err := decoder.Decode(&item); err != nil { + if err == io.EOF { + break + } + return nil, fmt.Errorf("decode json item: %w", err) + } + + if item == nil { + continue + } + + ip, err := p.extract(item) + if err != nil { + return nil, fmt.Errorf("extract ip: %w", err) + } + + ip = strings.TrimSpace(ip) + if !validator.IsValid(ip) { + continue + } + + ips = append(ips, ip) + if limit > 0 && uint(len(ips)) >= limit { + break + } + } + + return ips, nil +}