How to iterate through json array and print a formatted string?

I'm learning how to use logstash and I got things to mostly work. But I want to learn how to iterate through a json array and print a formatted result set. For example, I created a file called /root/test.log with the following content:

{"message":"Server log: Log title: 'Search Results';- Hits: {\"title\":\"Book 1\",\"author\":\"Jim\"},{\"title\":\"Book 2\",\"author\":\"Jen\"};---"}
{"message":"Server log: Log title: 'Search Results';- Hits: {\"title\":\"Book 3\",\"author\":\"Jess\"},{\"title\":\"Book 4\",\"author\":\"Jazz\"},{\"title\":\"Book 5\",\"author\":\"Jules\"};---"}

Then from my bash, I ran this command:

/usr/share/logstash/bin/logstash -e 'input {
file {
    type => "json"
    codec => "json"
    path => "/root/test.log"
    start_position => beginning 
  }
}
filter {
  grok {
    match => {
      "message" => "Server log: Log title: '%{DATA:logtitle}';- Hits: %{DATA:hitlist};---"
    }
  }
  mutate {
    add_field => { "hitstring" => "[%{hitlist}]" }
    remove_field => [ "hitlist" ]
  }
  json {
    source => "hitstring"
    target => "hits"
  }
  mutate {
    remove_field => [ "hitstring" ]
  }
}
output {
  email {
    to => "user@example.com"
    from => "user@example.com"
    subject => "Alert: %{logtitle}"
    body => "Here are your results\nBook1\nTitle: %{[hits][0][title]}\nAuthor: %{[hits][0][author]}\n\n\nBook2\nTitle: %{[hits][1][title]}\nAuthor: %{[hits][1][author]}\n\n"
    authentication => "plain"
    address => "smtp.mailtrap.io"
    domain => "smtp.mailtrap.io"
    port =>2525
    username => "my-username"
    password => "my-password"
  }
  stdout {
    codec => line {
      format => "Here are your results\nBook1\nTitle: %{[hits][0][title]}\nAuthor: %{[hits][0][author]}\n\n\nBook2\nTitle: %{[hits][1][title]}\nAuthor: %{[hits][1][author]}\n\n"
	}
  }
}'

This works except the second result is missing the Book3 Title: Book 5 Author: Jules. I could fix this by adding a Book3\nTitle: %{[hits][2][title]}\nAuthor: %{[hits][2][author]}. But is there a way to iterate through the json array and print out a string dynamically instead of hardcoding my string?

You would have to use ruby, something like

    json { source => "hitstring" target => "hits" }
    ruby {
        code => '
            h = event.get("hits")
            if h.is_a? Array
                s = ""
                h.each_index { |x|
                    title = h[x]["title"]
                    author = h[x]["author"]
                    s += "Book#{x+1}\nTitle: #{title}\nAuthor: #{author}\n"
                }
                event.set("[@metadata][list]", s)
            end

        '
    }
2 Likes