I am trying to parse below json. This has to throw me the error saying incorrect json format. But the parsor parses the json only till "value:15" and is not throwing any exception. How can I achieve this?
String json = { and : [{key: domain, value: cricket}, {key : STAT_CDE,value : 15}]}, { and : [{key: domain, value: football}, {key : STAT_CDE,value : 10}]}
Sample Code I am using:
import org.codehaus.jackson.map.ObjectMapper;
ObjectMapper mapper = new ObjectMapper();
mapper.readTree(json); //this line is not throwing me any exception
Here is the code snippet:
import org.codehaus.jackson.map.ObjectMapper;
public class JsonTestParse {
public static void main(String[] args) {
String json = "{ \"and\" : [{\"key\": \"domain\", \"op\": \"=\", \"value\": \"cricket\"}, {\"key\" : \"STAT_CDE\",\"op\" : \"=\",\"value\" : \"13\"}]},"+
"{ \"and\" : [{\"key\": \"domain\", \"op\": \"=\", \"value\": \"Football\"}, {\"key\" : \"STAT_CDE\",\"op\" : \"=\",\"value\" : \"10\"}]}";
System.out.println("json: " + json);
ObjectMapper mapper = new ObjectMapper();
try {
mapper.readTree(json);
} catch (Exception e) {
System.out.println("object mapper exp");
}
System.out.println("mapper complete");
}
}
And the output:
line 1: json: { "and" : [{"key": "domain", "op": "=", "value": "cricket"}, {"key" : "STAT_CDE","op" : "=","value" : "13"}]},{ "and" : [{"key": "domain", "op": "=", "value": "Football"}, {"key" : "STAT_CDE","op" : "=","value" : "10"}]}
line 2: mapper complete
The issue is that there is no problem with that json format! Syntactically, you're assigning a comma-delimited list to json, which is perfectly valid code - it will set json to the first item in the list and not do anything with the rest of the values.
After your code executes, json looks like this:
String json = { and : [{key: domain, value: cricket}, {key : STAT_CDE,value : 15}]}
And this value has been ignored entirely:
{ and : [{key: domain, value: football}, {key : STAT_CDE,value : 10}]}
As you can see, json is structured perfectly well.
Also, it looks like you're expecting a String object, but you're supplying a map instead.
Try the following:
String json = "{ and : [{key: domain, value: cricket}, {key : STAT_CDE,value : 15}]}, { and : [{key: domain, value: football}, {key : STAT_CDE,value : 10}]}"
And then parse json. This will most certainly fail because the keys are not enclosed with double quotes (the " character), which is a requirement of json format.
EDIT
To keep up to date with the question:
Here is a formatted view of the json you say you're working with:
{
"and" : [
{"key": "domain", "op": "=", "value": "cricket"},
{"key" : "STAT_CDE","op" : "=","value" : "15"}
]
},
{
"and" : [
{"key": "domain", "op": "=", "value": "football"},
{"key" : "STAT_CDE","op" : "=","value" : "10"}
]
}
The issue is that this is not a json object - it is TWO SEPARATE json objects, each of which is well-formed. I am guessing that ObjectMapper parses a full json structure, and ignores any trailing data without throwing an error.
If you'd like to capture the entire structure in json you will need to enclose them together, likely using an array:
[
{
"and" : [
{"key": "domain", "op": "=", "value": "cricket"},
{"key" : "STAT_CDE","op" : "=","value" : "15"}
]
},
{
"and" : [
{"key": "domain", "op": "=", "value": "football"},
{"key" : "STAT_CDE","op" : "=","value" : "10"}
]
}
]
Related
I am totally new to groovy script and would like some help to solve this out. I have a JSON response I want to manipulate and get desired parameters back by avoiding duplication. The Json response does not have indexes like 0,1,2.. that I can iterate through.
Here is the response that I want to work with:
{
"AuthenticateV2" : {
"displayName" : "Verification of authentication",
"description" : "notification ",
"smsTemplate" : "authentication.v2.0_sms",
"emailHeaderTemplate" : "v2.0_header",
"emailBodyTemplate" : "html",
"parameters" : {
"displayName" : "USER_DISPLAY_NAME",
"actionTokenURL" : "VERIFICATION_LINK",
"customToken" : "VERIFICATION_CODE"
},
"supportedPlans" : [
"connectGo"
]
},
"PasswordRecovery" : {
"displayName" : "Verification of password recovery",
"description" : "notification",
"smsTemplate" : "recovery.v1.0_sms",
"emailHeaderTemplate" : "recovery.v1.0_header",
"emailBodyTemplate" : "recovery.v1.0_body_html",
"parameters" : {
"displayName" : "USER_DISPLAY_NAME",
"actionTokenURL" : "VERIFICATION_LINK",
"customToken" : "VERIFICATION_CODE",
"adminInitiated" : false,
"authnId" : "AUTHENTICATION_IDENTIFIER",
"authnType" : "EMAIL",
"user" : {
"displayName" : "USER_DISPLAY_NAME"
}
},
"supportedPlans" : [
"connectGo"
]
},
"PasswordReset" : {
"displayName" : "password reset",
"description" : "notification",
"smsTemplate" : "recovery.v1.0_sms",
"emailHeaderTemplate" : "recovery.v1.0_header",
"emailBodyTemplate" : "html",
"parameters" : {
"displayName" : "USER_DISPLAY_NAME",
"user" : {
"displayName" : "USER_DISPLAY_NAME"
}
}
The expected output that I want to have:
{
"displayName" : "USER_DISPLAY_NAME",
"actionTokenURL" : "VERIFICATION_LINK",
"customToken" : "VERIFICATION_CODE",
"customToken" : "VERIFICATION_CODE",
"adminInitiated" : false,
"authnId" : "AUTHENTICATION_IDENTIFIER",
"authnType" : "EMAIL"
}
I need to retrieve all fields under parameters tag and also want to avoid duplication
You should first get familiar with parsing and producing JSON in Groovy.
Then, assuming the provided response is a valid JSON (it's not - there are 2 closing curlies (}) missing at the end) to get all the parameters keys merged into one JSON we have to convert the JSON string into a Map object first using JsonSlurper:
def validJsonResponse = '<your valid JSON string>'
Map parsedResponse = new JsonSlurper().parseText(validJsonResponse) as Map
Now, when we have a parsedResponse map we can iterate over all the root items in the response and transform them into the desired form (which is all the unique parameters keys) using Map::collectEntries method:
Map uniqueParameters = parsedResponse.collectEntries { it.value['parameters'] }
Finally, we can convert the uniqueParameters result back into a pretty printed JSON string using JsonOuput:
println JsonOutput.prettyPrint(JsonOutput.toJson(uniqueParameters))
After applying all the above we'll get the output
{
"displayName": "USER_DISPLAY_NAME",
"actionTokenURL": "VERIFICATION_LINK",
"customToken": "VERIFICATION_CODE",
"adminInitiated": false,
"authnId": "AUTHENTICATION_IDENTIFIER",
"authnType": "EMAIL",
"user": {
"displayName": "USER_DISPLAY_NAME"
}
}
If you want to get rid of user entry from the final output just remove it from the resulting uniqueParameters map (uniqueParameters.remove('user')) before converting it back to JSON string.
I am new to groovy and trying
1) from the output of prettyPrint(toJson()), I am trying to get a list of values from a specific key inside an json array using groovy. Using the below JSON output from prettyPrint example below, I am trying to create a list which consists only the values of the name key.
My Code:
def string1 = jiraGetIssueTransitions(idOrKey: jira_id)
echo prettyPrint(toJson(string1.data))
def pretty = prettyPrint(toJson(string1.data))
def valid_strings = readJSON text: "${pretty}"
echo "valid_strings.name : ${valid_strings.name}"
Output of prettyPrint(toJson(string1.data))is below JSON:
{
"expand": "places",
"places": [
{
"id": 1,
"name": "Bulbasaur",
"type": {
"grass",
"poison"
}
},
{
"id": 2,
"name": "Ivysaur",
"type": {
"grass",
"poison"
}
}
}
Expected result
valid_strings.name : ["Bulbasaur", "Ivysaur"]
Current output
valid_strings.name : null
The pretty printed JSON content is invalid.
If the JSON is valid, then names can be accessed as follows:
import groovy.json.JsonSlurper
def text = """
{
"expand": "places",
"places": [{
"id": 1,
"name": "Bulbasaur",
"type": [
"grass",
"poison"
]
},
{
"id": 2,
"name": "Ivysaur",
"type": [
"grass",
"poison"
]
}
]
}
"""
def json = new JsonSlurper().parseText(text)
println(json.places*.name)
Basically, use spray the attribute lookup (i.e., *.name) on the appropriate object (i.e., json.places).
I've used something similar to print out elements within the response in ReadyAPI
import groovy.json.*
import groovy.util.*
def json='[
{ "message" : "Success",
"bookings" : [
{ "bookingId" : 60002172,
"bookingDate" : "1900-01-01T00:00:00" },
{ "bookingId" : 59935582,
"bookingDate" : "1900-01-01" },
{ "bookingId" : 53184048,
"bookingDate" : "2019-01-15",
"testId" : "12803798123",
"overallScore" : "PASS" },
{ "bookingId" : 53183765,
"bookingDate" : "2019-01-15T13:45:00" },
{ "bookingId" : 52783312,
"bookingDate" : "1900-01-01" }
]
}
]
def response = context.expand( json )
def parsedjson = new groovy.json.JsonSlurper().parseText(response)
log.info parsedjson
log.info " Count of records returned: " + parsedjson.size()
log.info " List of bookingIDs in this response: " + parsedjson.bookings*.bookingId
Im using SwiftyJSON, Alamofire_SwiftyJSON and Alamofire libraries. I'm trying to parse my response but it returns nothing("definitions" fails to print).
JSON isn't empty it has got the response.
So, my code looks like the following (nothing fails, it all compiles)
Alamofire.request(request).responseSwiftyJSON { dataResponse in
if let JSON = dataResponse.result.value {
print(JSON)
if let definitions = JSON["results"]["lexicalEntries"]["entries"]["senses"]["definitions"].string {
print(definitions)
print("Hello")
}}
}
My response model looks like (this is not the whole response, that's just what I want to reach :
{
"results" : [
{
"language" : "en",
"id" : "ace",
"type" : "headword",
"lexicalEntries" : [
{
"language" : "en",
"entries" : [
{
"etymologies" : [
"Middle English (denoting the ‘one’ on dice): via Old French from Latin as ‘unity, a unit’"
],
"grammaticalFeatures" : [
{
"type" : "Number",
"text" : "Singular"
}
],
"homographNumber" : "000",
"senses" : [
{
"definitions" : [
"a playing card with a single spot on it, ranked as the highest card in its suit in most card games"
I think that my problem is in, should I add any parentheses or any symbols?
if let definitions = JSON["results"]["lexicalEntries"]["entries"]["senses"]["definitions"].string
You are not indexing the corresponding arrays in your JSON response, to access the definitions array you can simply use
JSON['results'][0]['lexicalEntries'][0]['entries'][0]['senses'][0]['definitions']
I have an index/type in ES which has the following type of records:
body "{\"Status\":\"0\",\"Time\":\"2017-10-3 16:39:58.591\"}"
type "xxxx"
source "11.2.21.0"
The body field is a JSON.So I want to search for example the records that have in their JSON body Status:0.
Query should look something like this(it doesn't work):
GET <host>:<port>/index/type/_search
{
"query": {
"match" : {
"body" : "Status:0"
}
}
}
Any ideas?
You have to change the analyser settings of your index.
For the JSON pattern you presented you will need to have a char_filter and a tokenizer which remove the JSON elements and then tokenize according to your needs.
Your analyser should contain a tokenizer and a char_filter like these ones here:
{
"tokenizer" : {
"type": "pattern",
"pattern": ","
},
"char_filter" : [ {
"type" : "mapping",
"mappings" : [ "{ => ", "} => ", "\" => " ]
} ],
"text" : [ "{\"Status\":\"0\",\"Time\":\"2017-10-3 16:39:58.591\"}" ]
}
Explanation: the char_filter will remove the characters: { } ". The tokenizer will tokenize by the comma.
These can be tested using the Analyze API. If you execute the above JSON against this API you will get these tokens:
{
"tokens" : [ {
"token" : "Status:0",
"start_offset" : 2,
"end_offset" : 13,
"type" : "word",
"position" : 0
}, {
"token" : "Time:2017-10-3 16:39:58.591",
"start_offset" : 15,
"end_offset" : 46,
"type" : "word",
"position" : 1
} ]
}
The first token ("Status:0") which is retrieved by the Analyze API is the one you were using in your search.
Depending on the HTTP_USER_AGENT I have to return a very specialized formatted version of a json structure to the client.
The json object is generated as usual with standard postgres functions.
Lets assume the generated json looks similar to this:
{
"return_code" : 0,
"payload" : {
"name" : "smith",
"age": 17,
"address" :{
"street" : "<whatever>",
"city" : "<anycity>"
}
}
}
Now under some circumstances I have to return this json in the following format:
{
"return_code" : 0,
"payload" : "{"name" : "smith", "age": 17, "address" :"{"street" : "<whatever>", "city" : "<anycity>"}"}"
}
As you can see the nested payload object should be returned as a string - masking ignored here for better readability.
Further else the address property should also be returned as a string, not as a json object.
My postgres code that should do this is simply:
response := jsonb_set(response, '{payload}', to_jsonb((response->'payload')::text));
But the result from the code above looks like:
{
"return_code" : 0,
"payload" : "{"name" : "smith", "age": 17, "address" :{"street" : "<whatever>", "city" : "<anycity>"}}"
}
Consider the quotes are missing (just two) for the address-object.
How can I fix this?
Thank You!
It seems to me that you need a further level of escaping / quoting on the address property, because you have:
Your substitution: { "payload" : { ... } } -> { "payload" : "{ ... }" }
Extra substitution: { "address": { ... } } -> { "address": "{ ... }" }
You'll need to do this before the existing line, so I think what you want is this (requires an extra jsonb variable, payload):
payload := jsonb_set(response->'payload', '{address}', to_jsonb((response->'payload'->address)::text));
response := jsonb_set(response, '{payload}', to_jsonb(payload::text));