Regular expression to match two JSON objects in Ready API - json

I am implementing a ready api project in which I have to compare two JSON objects.
Say Obj1 = {"A":"Test1","B:"Test2"} is an input.
I have a regular expression inside the script file in which I have
Obj = '''{"A":".*","B":".*"}''' and I tried to do assert obj1 == obj which didn't work.
Could some one tell me if script file in ReadyAPI doesn't support regular expression in such format?

With your example, you can do the comparison by parsing using JsonSlurper and get the keys before comparing as you are not bothered about the values.
See the example script:
def obj1 = """{
"A" : "Test1",
"B" : "Test2"
}"""
def obj2 = """{
"A" : "Test1a",
"B" : "Test2b"
}"""
def getJsonKeys = { jsonString ->
def json = new groovy.json.JsonSlurper().parseText(jsonString)
json.keySet()
}
assert getJsonKeys(obj1) == getJsonKeys(obj2)
Note that there are different values for the keys in obj2. But, just compared only keys.
Also note that if your json has more depth, you may to have to alter solution based on the data. Assuming that you have given right data.
You can quickly try it online demo

Related

Creating assertions using Groovy where JSON contains multiple objects with the same name

I'm currently writing some tests in ReadyAPI to test a new API that we are building. The API will return JSON in the following format:
{
"testJSON" : [
{
"test1" : "111",
"test2" : "ABC"
},
{
"test1" : "222",
"test2" : "DEF"
}
]
}
I have added the following Groovy code that breaks down the JSON and lists each value:
import groovy.json.JsonSlurper
def jsonResp = context.expand( '${GetTest#Response}' )
def jsonElements = new JsonSlurper().parseText(jsonResp)
for ( value in jsonElements.testInput ) {
value.each{
log.info "${it.key}:${it.value}"
}
}
What I am trying to do is to take this JSON response and compare it to a pre-defined list of data (using a Data Source within ReadyAPI). This data source will contain a column titled 'test1' and a column titled 'test2' -these will contain all the values expected for each object. So we would need to ensure that each test1 value from the datasource is displayed in the response JSON. And we'd also like to confirm that for each 'test1' we get the correct corresponding 'test2'.
So in example above, we'd want to prove that the response contained 'test1' values of 111 and 222, and that for 111 we got a 'test2' value of ABC etc.
The example above is a simplistic view of our new API and in reality it will contain a much larger number of fields and a lot more responses. So ideally, I don't want to have to hard code specific values within the Groovy script - which is why I'm trying to use a data sheet.
Has anyone had any experience of this sort of thing and can make any suggestions?
Thanks in advance for your help, please let me know if you need any more information.
Cheers,
Matt
"testJSON" is a list of objects containing properties "list1" and "list2".
Your datasource is also a list of objects (rows) containing properties (columns) "list1" and "list2".
Use a nested for loop to compare each expected object with each object in the response. Use a boolean flag to track whether test1 is missing from the response. When test1 is found, check the value of test2.
Here's the basic outline. I'm assuming test1 is a unique identifier for each object. You may also want to exit the inner loop when you do find test1, to be more efficient.
for (element in datasource) {
def foundTest1 = false
for (response in testJSON) {
if (response.test1 == element.test1){
foundTest1 = true
assert response.test2 == element.test2
// assert any number of other properties here
}
}
assert foundTest1 == true
}

Getting the only key of a Map from JsonSlurper

I have JSON that needs to be processed using Groovy. I am pretty sure that the JSON has only one key, with this format:
{ rootKey: [...] }
Where rootKey stands for different values (e.g. "customers", "stores", etc.).
Let's say I used JsonSlurper:
def map = jsonSlurper.parseText(myjson)
How do I obtain that rootKey string?
You should be able to use keySet method to get the keys which is a list. Since, you mentioned only key, you can use the first element as shown below:
def jsonString = """{
"rootKey": []
}"""
def json = new groovy.json.JsonSlurper().parseText(jsonString)
println json.keySet()[0]

Parsing nodes on JSON with Scala -

I've been asked to parse a JSON file to get all the buses that are over a specified speed inputed by the user.
The JSON file can be downloaded here
It's like this:
{
"COLUMNS": [
"DATAHORA",
"ORDEM",
"LINHA",
"LATITUDE",
"LONGITUDE",
"VELOCIDADE"
],
"DATA": [
[
"04-16-2015 00:00:55",
"B63099",
"",
-22.7931,
-43.2943,
0
],
[
"04-16-2015 00:01:02",
"C44503",
781,
-22.853649,
-43.37616,
25
],
[
"04-16-2015 00:11:40",
"B63067",
"",
-22.7925,
-43.2945,
0
],
]
}
The thing is: I'm really new to scala and I have never worked with json before (shame on me). What I need is to get the "Ordem", "Linha" and "Velocidade" from DATA node.
I created a case class to enclousure all the data so as to later look for those who are over the specified speed.
case class Bus(ordem: String, linha: Int, velocidade: Int)
I did this reading the file as a textFile and spliting. Although this way, I need to foreknow the content of the file in order to go to the lines after DATA node.
I want to know how to do this using a JSON parser. I've tried many solutions, but I couldn't adapt to my problem, because I need to extract all the lines from DATA node instead of nodes inside one node.
Can anyone help me?
PS: Sorry for my english, not a native speaker.
First of all, you need to understand the different JSON data types. The basic types in JSON are numbers, strings, booleans, arrays, and objects. The data returned in your example is an object with two keys: COLUMNS and DATA. The COLUMNS key has a value that is an array of strings and numbers. The DATA key has a value which is an array of arrays of strings.
You can use a library like PlayJSON to work with this type of data:
val js = Json.parse(x).as[JsObject]
val keys = (js \ "COLUMNS").as[List[String]]
val values = (js \ "DATA").as[List[List[JsValue]]]
val busses = values.map(valueList => {
val keyValues = (keys zip valueList).toMap
for {
ordem <- keyValues("ORDEM").asOpt[String]
linha <- keyValues("LINHA").asOpt[Int]
velocidade <- keyValues("VELOCIDADE").asOpt[Int]
} yield Bus(ordem, linha, velocidade)
})
Note the use of asOpt when converting the properties to the expected types. This operator converts the key-values to the provided type if possible (wrapped in Some), and returns None otherwise. So, if you want to provide a default value instead of ignoring other results, you could use keyValues("LINHA").asOpt[Int].getOrElse(0), for example.
You can read more about the Play JSON methods used here, like \ and as, and asOpt in their docs.
You can use Spark SQL to achieve it. Refer section under JSON Datasets here
In essence, Use spark APIs to load a JSON and register it as temp table.
You can run your SQL queries on the table from there.
As seen on #Ben Reich answer, that code works great. Thank you very much.
Although, my Json had some type problems on "Linha". As it can be seen on the JSON example that I put on the Question, there are "" and also numbers, e.g., 781.
When trying to do keyValues("LINHA").asOpt[Int].getOrElse(0), it was producing an error saying that value flatMap is not a member of Int.
So, I had to change some things:
case class BusContainer(ordem: String, linha: String, velocidade: Int)
val jsonString = fromFile("./project/rj_onibus_gps.json").getLines.mkString
val js = Json.parse(jsonString).as[JsObject]
val keys = (js \ "COLUMNS").as[List[String]]
val values = (js \ "DATA").as[List[List[JsValue]]]
val buses = values.map(valueList => {
val keyValues = (keys zip valueList).toMap
println(keyValues("ORDEM"),keyValues("LINHA"),keyValues("VELOCIDADE"))
for {
ordem <- keyValues("ORDEM").asOpt[String]
linha <- keyValues("LINHA").asOpt[Int].orElse(keyValues("LINHA").asOpt[String])
velocidade <- keyValues("VELOCIDADE").asOpt[Int]
} yield BusContainer(ordem, linha.toString, velocidade)
})
Thanks for the help!

How do I deserialize a JSON array using the Play API

I have a string that is a Json array of two objects.
> val ss = """[ {"key1" :"value1"}, {"key2":"value2"}]"""
I want to use the Play Json libraries to deserialize it and create a map from the key values to the objects.
def deserializeJsonArray(ss:String):Map[String, JsValue] = ???
// Returns Map("value1" -> {"key1" :"value1"}, "value2" -> {"key2" :"value2"})
How do I write the deserializeJsonArray function? This seems like it should be easy, but I can't figure it out from either the Play documentation or the REPL.
I'm a bit rusty, so please forgive the mess. Perhaps another overflower can come in here and clean it up for me.
This solution assumes that the JSON is an array of objects, and each of the objects contains exactly one key-value pair. I would highly recommend spicing it up with some error handling and/or pattern matching to validate the parsed JSON string.
def deserializeJsonArray(ss: String): Map[String, JsValue] = {
val jsObjectSeq: Seq[JsObject] = Json.parse(ss).as[Seq[JsObject]]
val jsValueSeq: Seq[JsValue] = Json.parse(ss).as[Seq[JsValue]]
val keys: Seq[String] = jsObjectSeq.map(json => json.keys.head)
(keys zip jsValueSeq).toMap
}

JSON to Groovy with JsonSlurper and unknown "string"

I am writing a Grails/Groovy app and I have a JSON object with a "string" name (grommet and widget) inside the params member that can change. That is, next time it might be acme and zoom. Here is the JSON:
def jx = """{
"job": "42",
"params": {
"grommet": {"name": "x", "data": "y"},
"widget": { "name": "a", "data": "b"}
}
}"""
I am trying to figure out how to get the string grommet . Code so far:
def dalist = new JsonSlurper().parseText(jx)
println dalist.job // Gives: 42
println dalist.params // Gives: [grommet:[name:x, data:y], widget:[name:a, data:b]]
println dalist.params[0] // Gives: null
Any idea how to get the string grommet? Iama going to keep hitting my head against a wall.
The params key on the JSON object is associated with a JSON object, not an array, so you cannot access it by index. JsonSlurper maps JSON objects to Groovy Maps, so you can access params by its keys, which are strings, e.g. dalist.params.grommet, which will give you the map [name: 'x', data: 'y'].
To access the keys on the params you can do dalist.params.keySet(), which will give you the list ['grommet', 'widget']. If you are interested in just knowing params keys, that should do the trick. If you need to get the 'grommet' string for some reason, you can do it by accessing the first element on that list, i.e. dalist.params.keySet()[0], but i don't know why you would want to know that. And i'm not sure if it is guaranteed that the first key of that map will always be 'grommet', as JSON objects are unordered by the spec (from json.org: An object is an unordered set of name/value pairs), but, in turn, Groovy maps are ordered (the default implementation is LinkedHashMap)... so i would assume that the order is preserved when parsing JSON to the Groovy world, but i'd try not to rely on that particular behavior hehe.
It's Map instance, try:
def params = dalist.params.entrySet() as List // entrySet() returns Set, but it's easier to use it as a List
println params
println params.size()
println params[0]
println params[0].key
println params[0].value
This might help you.
import groovy.json.JsonSlurper;
def jx='{"job":"42","params":{"grommet":{"name":"x","data":"y"},"widget":{"name":"a","data":"b"}}}'
def dalist = new JsonSlurper().parseText( jx )
assert dalist.params.getClass().name == "java.util.HashMap";
assert dalist.params.size() == 2;
def keys = dalist.params.collect{ a, b -> a}; // returns "[grommet, widget]"
assert !!dalist.params.get( "grommet" ) == true