How to apply left join on two JSON objects in groovy script - json

I have two JSON files:
first.json
[
{"a":"1", "b": "tmp"},
{"a":"2", "b": "tmp"},
{"a":"3", "b": "tmp"}
]
second.json
[
{"c":"1", "d": "tmp"},
{"c":"2", "d": "tmp"},
{"c":"4", "d": "tmp"}
]
output.json
[
{"a":"1", "b": "tmp", "c": "1" , "d": "tmp"},
{"a":"2", "b": "tmp", "c": "2" , "d": "tmp"},
{"a":"3", "b": "tmp", "c": "" , "d": ""}
]
I want to apply left join on two json files first.json and second.json on basis of two fields - "a" of first.json and "c" of second.json to get the output as output.json. How can I achieve the same using Groovy Script?
NOTE: I would like to achieve this in a single line if possible.

You would need to do something like this:
def firstJson = '''[
{"a":"1", "b": "tmp"},
{"a":"2", "b": "tmp"},
{"a":"3", "b": "tmp"}
]'''
def secondJson = '''[
{"c":"1", "d": "tmp"},
{"c":"2", "d": "tmp"},
{"c":"4", "d": "tmp"}
]'''
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
def slurpy = new JsonSlurper()
def first = slurpy.parseText(firstJson)
def second = slurpy.parseText(secondJson)
def result = first.collect { f ->
f + (second.find { it.c == f.a } ?: second[0].keySet().collectEntries { [it, ''] })
}
println JsonOutput.toJson(result)

Related

How can I convert to Json Object to Json Array in Karate?

I want to convert Json Object to Json Array in Karate to use 'match each' func.
I am getting to ('match each' failed, not a json array) error when I use match each func with Json Object.
Here is My Json Object:
{
{ "a": "q"
"b": "w",
"c": "t"
},
{ "a": "x"
"b": "y",
"c": "z"
}
}
And here is what I need:
[
{
{ "a": "q"
"b": "w",
"c": "t"
},
{ "a": "x"
"b": "y",
"c": "z"
}
}
]
Try this approach, using embedded expressions: https://github.com/intuit/karate#embedded-expressions
* def foo = { a: 1 }
* def list = [ '#(foo)' ]
* match each list == foo

Groovy: escape lower level JSON

I need to keep the first level JSON keys and convert the values to escaped strings, but only in case the values are also JSON objects. How can this be done in Groovy?
Input sample:
{
"a": "1",
"b": {
"c": "2",
"d": {
"e": "3"
}
},
"f": "4"
}
Desired result:
{
"a": "1",
"b": "{ \"c\": \"2\", \"d\": { \"e\": \"3\"} }",
"f": "4"
}
If you use JsonSlurper to parse the input JSON, then any nested JSON object will be represented as a LazyMap. You can use this information to collect all entries from the parsed JSON object (which is also a map) and convert any map object to its JSON string representation. You can convert any value to a JSON string representation using groovy.json.JsonOutput.toJson(object) method.
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
def input = '''{
"a": "1",
"b": {
"c": "2",
"d": {
"e": "3"
}
},
"f": "4"
}'''
def json = new JsonSlurper().parseText(input)
def escaped = json.collectEntries { k,v ->
[(k): v instanceof Map ? new JsonOutput().toJson(v) : v]
}
def output = new JsonOutput().prettyPrint(JsonOutput.toJson(escaped))
println output
Output:
{
"a": "1",
"b": "{\"c\":\"2\",\"d\":{\"e\":\"3\"}}",
"f": "4"
}

How to parse a Json array within a field while only getting certain fields of the object

I'm having some trouble using circe for a more complex extraction. If I have the below Json:
{
"data": [
{"a": "a-string", "b": "a-string", "c": "a-string"},
{"a": "a-string", "b": "a-string", "c": "a-string"},
{"a": "a-string", "b": "a-string", "c": "a-string"}
]
}
How could I use circe to get a list of those objects, but only containing the a and b fields?
Try defining a model which contains only a and b fields like so
case class Element(a: String, b: String)
For example,
import io.circe.generic.auto._
import io.circe.parser._
case class Element(a: String, b: String)
case class Data(data: List[Element])
val raw = """{"data": [{"a": "a-string", "b": "a-string", "c": "a-string"},{"a": "a-string", "b": "a-string", "c": "a-string"}, {"a": "a-string", "b": "a-string", "c": "a-string"}] }"""
decode[Data](raw).getOrElse(throw new RuntimeException)
outputs
res0: Data = Data(List(Element(a-string,a-string), Element(a-string,a-string), Element(a-string,a-string)))

KarateException Missing Property in path - JSON

I was trying to match particular variable from response and tried as below. But im getting error saying KarateException Missing Property in path $['Odata']. My question is: how we can modify so that we won't get this error?
Feature:
And match response.#odata.context.a.b contains '<b>'
Examples:
|b|
|b1 |
|b2 |
Response is
{
"#odata.context": "$metadata#Accounts",
"a": [
{
"c": 145729,
"b": "b1",
"d": "ON",
},
{
"c": 145729,
"b": "b2",
"d": "ON",
}
]
}
I think you are confused with the structure of your JSON. Also note that when the JSON key has special characters, you need to change the way you use them in path expressions. You can try paste the below in a new Scenario and see it work:
* def response =
"""
{
"#odata.context": "$metadata#Accounts",
"a": [
{
"c": 145729,
"b": "b1",
"d": "ON",
},
{
"c": 145729,
"b": "b2",
"d": "ON",
}
]
}
"""
* match response['#odata.context'] == '$metadata#Accounts'
* match response.a[0].b == 'b1'
* match response.a[1].b == 'b2'

Julia | DataFrame conversion to JSON

I have a dataframe in Julia like df = DataFrame(A = 1:4, B = ["M", "F", "F", "M"]). I have to convert it into a JSON like
{
"nodes": [
{
"A": "1",
"B": "M"
},
{
"A": "2",
"B": "F"
},
{
"A": "3",
"B": "F"
},
{
"A": "4",
"B": "M"
}
]
}
Please help me in this.
There isn't a method in DataFrames to do this. In a github issue where the following snippet, using JSON.jl, is offered as a method to write json:
using JSON
using DataFrames
function df2json(df::DataFrame)
len = length(df[:,1])
indices = names(df)
jsonarray = [Dict([string(index) => (isna(df[index][i])? nothing : df[index][i])
for index in indices])
for i in 1:len]
return JSON.json(jsonarray)
end
function writejson(path::String,df::DataFrame)
open(path,"w") do f
write(f,df2json(df))
end
end
JSONTables package provides JSON conversion to/from Tables.jl-compatible sources like DataFrame.
using DataFrames
using JSONTables
df = DataFrame(A = 1:4, B = ["M", "F", "F", "M"])
jsonstr = objecttable(df)