logstash-plugins/logstash-filter-json

Exception :exception=>#<TypeError: can't convert Java::JavaUtil::ArrayList into Hash>

fedelemantuano opened this issue · 8 comments

Hi,

I can't parse a valid json with Logstash. I have the follow error:

Trouble parsing json {:source=>"message", :raw=>"[    [ { \"key1\": \"value1\" } ],    [ { \"key2\": \"value2\" } ]]", :exception=>#<TypeError: can't convert Java::JavaUtil::ArrayList into Hash>, :level=>:warn}

I'm trying to parse a complex valid json file, but I reproduced the error with the follow json:

fedelemantuano@solaria ~/Downloads $ cat test.json  
[
    [ { "key1": "value1" } ],
    [ { "key2": "value2" } ]
]
fedelemantuano@solaria ~/Downloads $ jsonlint test.json 
test.json: ok

I can parse with python:

In [8]: import json

In [9]: test = json.loads('[ [ { "key1": "value1" } ], [ { "key2": "value2" } ] ]')

In [10]: test
Out[10]: [[{u'key1': u'value1'}], [{u'key2': u'value2'}]]

but with Logstash I have the follow error:

Trouble parsing json {:source=>"message", :raw=>"[    [ { \"key1\": \"value1\" } ],    [ { \"key2\": \"value2\" } ]]", :exception=>#<TypeError: can't convert Java::JavaUtil::ArrayList into Hash>, :level=>:warn}
{
       "message" => "[    [ { \"key1\": \"value1\" } ],    [ { \"key2\": \"value2\" } ]]",
      "@version" => "1",
    "@timestamp" => "2015-10-07T16:30:22.326Z",
       "headers" => {
           "content_type" => "application/x-www-form-urlencoded",
         "request_method" => "POST",
           "request_path" => "/",
            "request_uri" => "/",
           "http_version" => "HTTP/1.1",
        "http_user_agent" => "curl/7.38.0",
              "http_host" => "koro.certego.local:8080",
            "http_accept" => "*/*",
         "content_length" => "59"
    },
          "tags" => [
        [0] "_jsonparsefailure"
    ]
}

Can we help me, please?

Buongiorno @fedelemantuano

This doesn't look like a valid json, i understand that jsonlint is saying that it is, but i think that this json should look like:

{
    "jsoninput": [
        {
            "key1": "value1"
        },
        {
            "key2": "value2"
        }
    ]
}

Then, the output from logstash will be something like:

{
       "message" => "{\"jsoninput\":[{\"key1\":\"value1\"},{\"key2\":\"value2\"}]}",
      "@version" => "1",
    "@timestamp" => "2015-10-08T13:02:54.011Z",
          "host" => "Gabriels-MacBook-Pro.local",
     "jsoninput" => [
        [0] {
            "key1" => "value1"
        },
        [1] {
            "key2" => "value2"
        }
    ]
}

Hi @gmoskovicz thanks for the answer.

I'm using the JsonML library (http://www.jsonml.org/) to convert HTML in JSON and the output JSON is like this:

[
    "ul",
    [
        "li",
        {
            "style": "color:red"
        },
        "First Item"
    ],
    [
        "li",
        {
            "title": "Some hover text.",
            "style": "color:green"
        },
        "Second Item"
    ],
    [
        "li",
        [
            "span",
            {
                "class": "code-example-third"
            },
            "Third"
        ],
        " Item"
    ]
]

I used the follow validators:

and for them is a valid JSON. I can parsing with python.
It's possible itegrate Logstash JSON plugin to manage this JSON?

@fedelemantuano and @gmoskovicz
Firstly, the input is correct JSON.
Secondly, this is a bug. https://github.com/logstash-plugins/logstash-filter-json/blob/master/lib/logstash/filters/json.rb#L70 does not test for ArrayList as well.
Thirdly, this will be automatically fixed in LS v2.0 (due in a few weeks).
Fourthly, I will fix this bug in a gem version that will work with LS 1.5.4

Hi,
I have the same issue with logstash 2.1.1. I tested the same json and I had another error message:

Trouble parsing json {:source=>"message", :raw=>"[    \"ul\",    [        \"li\",        {            \"style\": \"color:red\"        },        \"First Item\"    ],    [        \"li\",        {            \"title\": \"Some hover
 text.\",            \"style\": \"color:green\"        },        \"Second Item\"    ],    [        \"li\",        [            \"span\",            {                \"class\": \"code-example-third\"            },            \"Th
ird\"        ],        \" Item\"    ]]", :exception=>#<RuntimeError: Parsed JSON arrays must have a destination in the configuration>, :level=>:warn}

Maybe there is the same bug.

@fedelemantuano Looks like this bug was not fixed. @guyboertje can you confirm this?

Yes @gmoskovicz the bug is open, but in last answer @guyboertje told me:

Thirdly, this will be automatically fixed in LS v2.0 (due in a few weeks).
Fourthly, I will fix this bug in a gem version that will work with LS 1.5.4

and the error message is changed from TypeError: can't convert Java::JavaUtil::ArrayList into Hash to exception=>#<RuntimeError: Parsed JSON arrays must have a destination in the configuration> with the same json.

@fedelemantuano, @gmoskovicz - the root cause is the same. The problem shows itself differently.
I understand the full picture now.
You need to specify a target field config option. See the docs
This is why @gmoskovicz suggested that it is not valid JSON - I think Gabriel meant invalid in the LS context.

If your config is:

filter {
  json {
    # Parse message as JSON
    source => "message"
  }
}

For an Event like this:

  "message" => "{\"hello\" : \"world\"}"
  "other"   => "value"

Note that the source field is a JSON object. In this case, a target is not needed because the JSON objects keys and values are transferred to the Event so you get this:

  "message" => "{\"hello\" : \"world\"}"
  "other"   => "value"
  "hello"   => "world"

If, as in @fedelemantuano case the source field is not a JSON object then a target field must be set in the codec config. Imagine your config is:

filter {
  json {
    # Parse message as JSON, store the results in the 'html' field
    source => "message"
    target => "html"
  }
}

For this Event:

  "message" => "[ \"li\", { \"style\": \"color:red\" }, \"First Item\" ]"
  "other"   => "value"

you get:

  "message" => "{\"hello\" : \"world\"}"
  "other"   => "value"
  "html"   => [ "li", { "style" => "color:red" }, "First Item" ]

Note that field "html" now contains Ruby objects parsed from your JSON array.

So in closing, the original error "TypeError: can't convert Java::JavaUtil::ArrayList into Hash" was fixed.

@fedelemantuano - can you close this now?

Yes,

I tested without elasticsearch output plugin, and the json filter work.

Now I have a issue in elasticsearch:

MapperParsingException[object mapping for [message_parsed] tried to parse field [null] as object, but found a concrete value]

But also for me this issue is solved.

Thank you so much.