Skip to content

Commit

Permalink
Make sure JSON parser returns Hash
Browse files Browse the repository at this point in the history
It is wrong for Parser to return a record that is not Hash.
Subsequent processing may result in errors.

Signed-off-by: Daijiro Fukuda <[email protected]>
  • Loading branch information
daipom authored and kenhys committed Apr 4, 2024
1 parent 1a2759c commit d5c32e8
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 5 deletions.
25 changes: 20 additions & 5 deletions lib/fluent/plugin/parser_json.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,31 @@ def configure_json_parser(name)
end

def parse(text)
record = @load_proc.call(text)
time = parse_time(record)
if @execute_convert_values
time, record = convert_values(time, record)
parsed_json = @load_proc.call(text)

if parsed_json.is_a?(Hash)
yield parse_one_record(parsed_json)
elsif parsed_json.is_a?(Array)
parsed_json.each do |record|
unless record.is_a?(Hash)
yield nil, nil
next
end
yield parse_one_record(record)
end
else
yield nil, nil
end
yield time, record

rescue @error_class, EncodingError # EncodingError is for oj 3.x or later
yield nil, nil
end

def parse_one_record(record)
time = parse_time(record)
convert_values(time, record)
end

def parser_type
:text
end
Expand Down
56 changes: 56 additions & 0 deletions test/plugin/test_parser_json.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,60 @@ def test_yajl_parse_io_with_buffer_smaller_than_input
end
end
end

sub_test_case "various record pattern" do
data("Only string", { record: '"message"', expected: [nil] }, keep: true)
data("Only string without quotation", { record: "message", expected: [nil] }, keep: true)
data("Only number", { record: "0", expected: [nil] }, keep: true)
data(
"Array of Hash",
{
record: '[{"k1": 1}, {"k2": 2}]',
expected: [{"k1" => 1}, {"k2" => 2}]
},
keep: true,
)
data(
"Array of both Hash and invalid",
{
record: '[{"k1": 1}, "string", {"k2": 2}, 0]',
expected: [{"k1" => 1}, nil, {"k2" => 2}, nil]
},
keep: true,
)
data(
"Array of all invalid",
{
record: '["string", 0, [{"k": 0}]]',
expected: [nil, nil, nil]
},
keep: true,
)
def test_oj(data)
i = 0
@parser.configure('json_parser' => "oj")
@parser.instance.parse(data[:record]) { |time, record|
assert_equal(data[:expected][i], record)
i += 1
}
end

def test_yajl(data)
i = 0
@parser.configure('json_parser' => "yajl")
@parser.instance.parse(data[:record]) { |time, record|
assert_equal(data[:expected][i], record)
i += 1
}
end

def test_json(json)
i = 0
@parser.configure('json_parser' => "json")
@parser.instance.parse(data[:record]) { |time, record|
assert_equal(data[:expected][i], record)
i += 1
}
end
end
end

0 comments on commit d5c32e8

Please sign in to comment.