Set root for json codec

Using the json_codec on input I get all my fields parsed at the root level. I like to specify a name for the subfield for the items.
So right now with { "a" : "b", "c" : "d" } to get a = b and c = d. I'd like to get myname.a = b and myname.c = d.

I'm concerned about doing this in a ruby filter as I saw a post that the json_codec is much faster than a ruby filter.

Any thoughts?

The JSON codec does not support this behaviour.

Your best bet is likely to use the JSON filter, which can take the value of a JSON string field, parse it, and place the result somewhere. Assuming you use your input's default codec and the raw contents are placed into message, this would do the trick:

filter {
  json {
    source => "message"
    target => "myname"
    remove_field => "message"
  }
}

The remove_field directive is optional and is only invoked on success.

Thanks Ry, The problem I'm running into with that solution is the message maybe be an array of json objects. [{"a":"b"},{"a":"c"}]. In this case json_codec handles properly but json filter is unhappy as the entire array came in as a single message / document. Any ideas to handle the array format?

Again thank you for the quick response.

The json filter will handle an array provided that you use the target option.

Thanks Badger. What I am seeing is this:

With this json filter:

json {

skip_on_invalid_json => true

source => "message"

target => "mytarget"

remove_field => [ "message"]

}

I get this as my document.

Am I implementing the filter incorrectly to get two documents?

If you want two documents then pass the array to a split filter.

Thanks Badger. I ended up with this in my filter to get the desired result.

    json {
      skip_on_invalid_json => true
      source => "message"
      target => "myfield"
      remove_field => [ "message"]
    }

    # If the data is in an array then add a tag to allow for splitting each index into own event.
    ruby {
      code => "if event.get('myfield').is_a? Hash
                event.tag('ishash')
               end"
    }

    # if isHash is not set then go ahead and split without this check any fields that aren't arrays throw WARN.
    if "ishash" not in [tags] {
      split {
        field => "myfield"
      }
    }