# Working with JSON array of objects via Ruby code block

**URL:** <https://discuss.elastic.co/t/working-with-json-array-of-objects-via-ruby-code-block/289009>\
**Category:** Logstash\
**Created:** [November 11, 2021, 5:41pm UTC](https://discuss.elastic.co/t/working-with-json-array-of-objects-via-ruby-code-block/289009 "2021-11-11T17:41:45Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Colin\_K](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/colin_k/32/78869_2.png) [@Colin\_K](https://discuss.elastic.co/u/Colin_K)\
**Post date:** [November 11, 2021, 5:41pm UTC](https://discuss.elastic.co/t/working-with-json-array-of-objects-via-ruby-code-block/289009/1 "2021-11-11T17:41:45Z")

</div>

I have a JSON array of nested objects. I wrote a filter

```auto
json { 
  source => ['body']
  target => "parsed"
}

ruby {
  code => "mapped = event.get('parsed').map{
    |h| [h['k1'], h['k2'],h['k3'],h['k4']]
  }; event.set('mapped', mapped)"
}

```

I have two questions

1. there is another key, say h['k5']. This key contains a json itself. I can access h['k5'] but I cannot access it's nested objects. For example I try h['k5']['l1'] for one of it's keys and that does not work. What do I need to do to access it's fields from the ruby code?

\<Resolved, was using bad keys. My bad. #2 is still an open question.\>

1. Currently in above I am returning an array. If I wish to return a json Object instead of an Array, how do I do that?

---

<div class="post-metadata">

**Author:** ![Badger](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/badger/32/25190_2.png) [@Badger](https://discuss.elastic.co/u/Badger)\
**Post date:** [November 11, 2021, 5:55pm UTC](https://discuss.elastic.co/t/working-with-json-array-of-objects-via-ruby-code-block/289009/2 "2021-11-11T17:55:56Z")

</div>

> [@Colin\_K](#):
>
> that does not work

What does that mean, and what does your data actually look like once it is parsed. Can you show an event from

```
output { stdout { codec => rubydebug } }

```

---

<div class="post-metadata">

**Author:** ![Colin\_K](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/colin_k/32/78869_2.png) [@Colin\_K](https://discuss.elastic.co/u/Colin_K)\
**Post date:** [November 11, 2021, 9:18pm UTC](https://discuss.elastic.co/t/working-with-json-array-of-objects-via-ruby-code-block/289009/3 "2021-11-11T21:18:22Z")

</div>

Regarding 1) I resolved my issue, I was using bad keys. So 1) does work.

#2 is still an open issue. Instead of returning an array using the map function, what is the appropriate way to return a json object using the map function body?

---

<div class="post-metadata">

**Author:** ![Badger](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/badger/32/25190_2.png) [@Badger](https://discuss.elastic.co/u/Badger)\
**Post date:** [November 11, 2021, 9:43pm UTC](https://discuss.elastic.co/t/working-with-json-array-of-objects-via-ruby-code-block/289009/4 "2021-11-11T21:43:11Z")

</div>

You have not explained what you want the result to look like. There are no JSON objects in logstash. You wrote your code so that .map returns an array. You could have returned something else.

---

<div class="post-metadata">

**Author:** ![Colin\_K](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/colin_k/32/78869_2.png) [@Colin\_K](https://discuss.elastic.co/u/Colin_K)\
**Post date:** [November 11, 2021, 11:46pm UTC](https://discuss.elastic.co/t/working-with-json-array-of-objects-via-ruby-code-block/289009/5 "2021-11-11T23:46:50Z")

</div>

I'm specifically asking what is a good approach for returning a valid JSON object. I could take my key values and form JSON from strings. For example if h[k1] .. h[kn] all return strings, I could try writing JSON using String interpolation. Example to add a key for each value extracted.

But that seems rather crude and messy. Is there an alternative?

Can I use the JSON module from ruby's stdlib and JSON.generate(...) on a ruby hash?

---

<div class="post-metadata">

**Author:** ![Badger](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/badger/32/25190_2.png) [@Badger](https://discuss.elastic.co/u/Badger)\
**Post date:** [November 12, 2021, 12:49am UTC](https://discuss.elastic.co/t/working-with-json-array-of-objects-via-ruby-code-block/289009/6 "2021-11-12T00:49:03Z")

</div>

> [@Colin\_K](#):
>
> I'm specifically asking what is a good approach for returning a valid JSON object.

The ask does not make sense to me. There are no JSON objects in a logstash pipeline. Fields can be objects that contain other objects, but that does not make them JSON.

Do you want serialized JSON in a field? You could install the [json\_encode](https://www.elastic.co/guide/en/logstash/current/plugins-filters-json_encode.html) filter for that.

---

<div class="post-metadata">

**Author:** ![Colin\_K](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/colin_k/32/78869_2.png) [@Colin\_K](https://discuss.elastic.co/u/Colin_K)\
**Post date:** [November 12, 2021, 6:10pm UTC](https://discuss.elastic.co/t/working-with-json-array-of-objects-via-ruby-code-block/289009/7 "2021-11-12T18:10:52Z")

</div>

> Do you want serialized JSON in a field?

Doesn't my question of JSON.generate(...) imply that I am trying to serialize JSON?

> You could install the [json\_encode](https://www.elastic.co/guide/en/logstash/current/plugins-filters-json_encode.html) filter for that.

Can I use json\_encode by surrounding the ruby code block? Then do I need to nest the ruby / code block inside the json\_encode? I assume I would need to escape the json\_encode "arguments" if that were the case , which sounds difficult.

**Let me try make the problem clear to you.** I have the following code. I am currently outputting a ruby array .

```auto
json { 
  source => ['body']
  target => "parsed"
}

ruby {
  code => "mapped = event.get('parsed').map{
    |h| [h['k1'], h['k2'],h['k3'],h['k4']]
  }; event.set('mapped', mapped)"
}

```

I prefer to output serialized JSON (serialized JSON is encoded objects in a string).

Requirements -\>

Instead of returning an array in the map function, return the serialized Json string. For each key 'k1' , 'kn' use a value key1..keyN for the corresponding JSON object.

Example {"key1":\<h['k1']\>, ..., "keyN":\<h['kN']\>} where \<h['k1']\> is the value extracted by the map function.

1. create a structured serialized JSON (serialized JSON is encoded objects in a string)
2. do so from within a ruby code block

---

<div class="post-metadata">

**Author:** ![Badger](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/badger/32/25190_2.png) [@Badger](https://discuss.elastic.co/u/Badger)\
**Post date:** [November 12, 2021, 6:41pm UTC](https://discuss.elastic.co/t/working-with-json-array-of-objects-via-ruby-code-block/289009/8 "2021-11-12T18:41:53Z")

</div>

> [@Colin\_K](#):
>
> Let me try make the problem clear to you.

You are not making it clear. Instead of showing what the input data looks like and exactly what result you want, you are showing us examples of operations upon unseen data that do not produce what you want.

---

<div class="post-metadata">

**Author:** ![Colin\_K](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/colin_k/32/78869_2.png) [@Colin\_K](https://discuss.elastic.co/u/Colin_K)\
**Post date:** [November 12, 2021, 7:02pm UTC](https://discuss.elastic.co/t/working-with-json-array-of-objects-via-ruby-code-block/289009/9 "2021-11-12T19:02:50Z")

</div>

Input data to the ruby is a JSON array of objects as explained.

I'll figure it out on my own and post the solution.

---

<div class="post-metadata">

**Author:** ![Colin\_K](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/colin_k/32/78869_2.png) [@Colin\_K](https://discuss.elastic.co/u/Colin_K)\
**Post date:** [November 15, 2021, 7:26pm UTC](https://discuss.elastic.co/t/working-with-json-array-of-objects-via-ruby-code-block/289009/10 "2021-11-15T19:26:47Z")

</div>

> Can I use the JSON module from ruby's stdlib and JSON.generate(...) on a ruby hash?

To answer my own question: It took me awhile to lock down the syntax. But I was able to use init and JSON.generate along with the map function to create a JSON string via the Ruby code block.

```auto
init => "require 'JSON'"

```

However one possibly very tricky problem remains.

My output now looks like

```auto
"body" : [
"{\"key1\" : \"value1\",\"keyn\" : \"valuen\"}",
"{\"key1\" : \"value1\",\"keyn\" : \"valuen\"}",
"{\"key1\" : \"value1\",\"keyn\" : \"valuen\"}"
]

```

That is each JSON object is wrapped inside a String in escaped syntax. I think it might be very difficult to extract each object from it's String wrapper because claims that LS needed Ruby to work with Arrays in the first place. However I will see if I can simply apply another filter to extract the String. I hope I can extract the String and complete this work quickly.

---

<div class="post-metadata">

**Author:** ![Colin\_K](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/colin_k/32/78869_2.png) [@Colin\_K](https://discuss.elastic.co/u/Colin_K)\
**Post date:** [November 15, 2021, 9:14pm UTC](https://discuss.elastic.co/t/working-with-json-array-of-objects-via-ruby-code-block/289009/11 "2021-11-15T21:14:29Z")

</div>

I was able to solve my problem. It was not necessary to use the JSON module. Returning a Ruby Hash and the output from Logstash seems to be a valid JSON object.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [December 13, 2021, 9:14pm UTC](https://discuss.elastic.co/t/working-with-json-array-of-objects-via-ruby-code-block/289009/12 "2021-12-13T21:14:44Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
