Grails - rendering a JSON - json

I am inserting a JSON value into a H2 database using GORM in the domain i have two column
String clobs
Date date
static mapping = {
datasource 'json'
clobs sqlType: 'clob'
}
static constraints = {
}
}
from the controller i call the service method
def createJson(){
log.debug("Inserting Values")
def builder = new JsonBuilder()
builder.message {
header {
from('mrhaki')
to 'Groovy Users', 'Java Users'
}
body "Check out Groovy's gr8 JSON support."
}
println "builder value before inserting is: "+ builder
def jsonExec = new JsonOrm(clobs: builder.toString(), date: new Date())
println "the builder value: "+ jsonExec.clobs
println "the date value: " + jsonExec.date
jsonExec.save()(failOnError:true)
println "values saved successfully in the table!!!!!"
}
while executing this is the error i am getting in the browser
URI
/SampleProject/jsonOrm/index
Class
groovy.lang.MissingMethodException
Message
No signature of method: com.ws.JsonOrm.call() is applicable for argument types: (java.util.LinkedHashMap) values: [[failOnError:true]] Possible solutions: wait(), last(), save(), any(), getAll(), wait(long)

To render a json string (from the CLOB), you can just parse string first and then render the json from it like this:
Map map = JSON.parse(jsonString)
render (map as JSON)

You're converting the entire CLOB object, you just want the 'contents', try:
stmt = row["JSON"]?.asciiStream.text

Related

How to get the Id attribute of return json body response in groovy

After calling a MS Graph API using HttpBuilder which return user information, I would like to return the Id attribute of the Json response
The complete Json response is as below :
{
#odata.context=https://graph.microsoft.com/v1.0/$metadata#users,
value=[{
businessPhones=[],
displayName=Serge Cal GMAIL,
givenName=null,
jobTitle=null,
mail=user1.tom#gmail.com,
mobilePhone=null,
officeLocation=null,
preferredLanguage=null,
surname=null,
userPrincipalName=user1.tom_gmail.com#EXT##SCALDERARA.onmicrosoft.com,
id=253bca1d-6c03-441f-92e4-e206c7d180f7
}]
}
For doing so I have a groovy method define as below :
public String getUserIdByEmailQuery(String AuthToken,String userEmail){
String _userId
def http = new HTTPBuilder(graph_base_user_url +"?")
http.request(GET) {
requestContentType = ContentType.JSON
uri.query = [ $filter:"mail eq '$userEmail'".toString() ]
headers.'Authorization' = "Bearer " + AuthToken
response.success = { resp, json ->
**_userId=json["value"]["id"]**
}
// user ID not found : error 404
response.'404' = { resp ->
_userId = 'Not Found'
}
}
_userId
}
With this update the reponse value is [xxx-xxx-xxx-xxx-xxx-], which is correct excpet that it suround the value with []
Any idea ?
regards
The original problem was caused by the wrong expression to get the id and since you have got the id list [xxx-xxx-xxx-xxx, xxx-xxx-xxx-xxx, ...] by json["value"]["id"], so you just need to use json["value"]["id"][0] to get the first id of the list.
And this expression json["value"][0]["id"] might also work.
Update:
You can use groovy.json.JsonSlurper to help you parse the json and get the id value.
import groovy.json.JsonSlurper
JsonSlurper slurper = new JsonSlurper()
Map parsedJson = slurper.parseText(json)
String idValue = parsedJson.value[0].id

Parse JSON using groovy script (using JsonSlurper)

I am just two days old to groovy, I need to parse a json file with below structure. My actual idea is I need to run a set of jobs in different environments based on different sequences, so I came up with this format of json as a input file to my groovy
{
"services": [{
"UI-Service": [{
"file-location": "/in/my/server/location",
"script-names": "daily-batch,weekly-batch,bi-weekly-batch",
"seq1": "daily-batch,weekly-batch",
"seq2": "daily-batch,weekly-batch,bi-weekly-batch",
"DEST-ENVT_seq1": ["DEV1", "DEV2", "QA1", "QA2"],
"DEST-ENVT_seq2": ["DEV3", "DEV4", "QA3", "QA4"]
}]
}, {
"Mobile-Service": [{
"file-location": "/in/my/server/location",
"script-names": "daily-batch,weekly-batch,bi-weekly-batch",
"seq1": "daily-batch,weekly-batch",
"seq2": "daily-batch,weekly-batch,bi-weekly-batch",
"DEST-ENVT_seq1": ["DEV1", "DEV2", "QA1", "QA2"],
"DEST-ENVT_seq2": ["DEV3", "DEV4", "QA3", "QA4"]
}]
}]
}
I tried below script for parsing the json
def jsonSlurper = new JsonSlurper()
//def reader = new BufferedReader(new InputStreamReader(new FileInputStream("in/my/location/config.json"),"UTF-8"))
//def data = jsonSlurper.parse(reader)
File file = new File("in/my/location/config.json")
def data = jsonSlurper.parse(file)
try{
Map jsonResult = (Map) data;
Map compService = (Map) jsonResult.get("services");
String name = (String) compService.get("UI-Service");
assert name.equals("file-location");
}catch (E){
println Exception
}
I need to first read all the services (UI-service, Mobile-Service, etc..) then their elements and their value
Or you could do something like:
new JsonSlurper().parseText(jsonTxt).services*.each { serviceName, elements ->
println serviceName
elements*.each { name, value ->
println " $name = $value"
}
}
But it depends what you want (and you don't really explain in the question)
Example for reading from JsonParser object:
def data = jsonSlurper.parse(file)
data.services.each{
def serviceName = it.keySet()
println "**** key:${serviceName} ******"
it.each{ k, v ->
println "element name: ${k}, element value: ${v}"
}
}
other options:
println data.services[0].get("UI-Service")["file-location"]
println data.services[1].get("Mobile-Service").seq1

how to put pretty JSON into REST api

I am trying to build a REST service which accepts XML and convert it into JSON and call external Service which accepts JSON and put my JSON into it. I am able to put the json without pretty but I want to PUT the json in pretty format. Please suggest how to do, below is my code ...
package com.mypackge
import grails.converters.JSON
import grails.rest.RestfulController
import grails.plugins.rest.client.RestBuilder
class RestCustomerController extends RestfulController {
/*
static responseFormats = ['json', 'xml']
RestCustomerController() {
super(Customer)
}
*/
def index() {
convertXmlToJson()
}
def myJson = ''
def convertXmlToJson() {
def xml = ''' <Customer>
<customerid>9999999999999</customerid>
<ssn>8888</ssn>
<taxid>8888</taxid>
<address>
<addressline1>Yamber Ln</addressline1>
<addressline1>8664 SE</addressline1>
<city>CCCCC</city>
<state>CC</state>
<zipcode>97679</zipcode>
</address>
<firstname>Scott</firstname>
<middlename></middlename>
<lastname>David</lastname>
<account>
<accountno>576-294738943</accountno>
<accounttype>Lease</accounttype>
<accountsubtype></accountsubtype>
<accountstatus>complete</accountstatus>
<firstname>Scott</firstname>
<middlename></middlename>
<lastname>David</lastname>
<businessname></businessname>
<billingsystem>yoiuhn</billingsystem>
<brand></brand>
<plantype></plantype>
<billingaddress>
<addressline1>Yamber Ln</addressline1>
<addressline1>8664 SE </addressline1>
<city>CCCCC</city>
<state>CC</state>
<zipcode>97679</zipcode>
</billingaddress>
<job>
<jobid>8276437463728</jobid>
<jobstatus>SUCCESS</jobstatus>
</job>
</account>
</Customer>
'''.stripMargin()
// Parse it
def parsed = new XmlParser().parseText( xml )
def myId = parsed.customerid.text()
// Deal with each node:
def handle
handle = { node ->
if( node instanceof String ) {
node
}
else {
[ (node.name()): node.collect( handle ) ]
}
}
// Convert it to a Map containing a List of Maps
def jsonObject = [ (parsed.name()): parsed.collect { node ->
[ (node.name()): node.collect( handle ) ]
} ]
def json = new groovy.json.JsonBuilder(jsonObject) //.toPrettyString()
// Check it's what we expected
def mmyresp
try{
mmyresp = putRequest(myId,json)
}catch(Exception e) {
mmyresp = 'Please Validate JSON ....'
}
}
def putRequest(String id, JSON myJson) {
String url = "http://foo.com/customer/external/"+id
def rest = new RestBuilder()
def resp = rest.put(url){
contentType "application/json"
json{
myJson
}
}
return resp
}
}
The record is added in below format ...
{"Customer":[{"customerid":["9999999999999"]},{"ssn":["8888"]},
{"taxid":["8888"]},{"address":[{"addressline1":["Yamber Ln"]},
{"addressline1":["8664 SE"]},{"city":["CCCCC"]},{"state":["CC"]},{"zipcode":["97679"]}]},
{"firstname":["Scott"]},{"middlename":[]},{"lastname":["David"]},{"businessname":[]},
{"account":[{"accountno":["576-294738943"]},{"accounttype":["Lease"]},{"accountsubtype":[]},
{"accountstatus":["complete"]},{"firstname":["Scott"]},{"middlename":[]},{"lastname":["David"]},
{"businessname":[]},{"billingsystem":["yoiuhn"]},{"brand":[]},{"plantype":[]},
{"billingaddress":[{"addressline1":["Yamber Ln"]},{"addressline1":["8664 SE"]},
{"city":["CCCCC"]},{"state":["CC"]},{"zipcode":["97679"]}]},{"job":[{"jobid":["8276437463728"]},
,{"jobstatus":["SUCCESS"]}]}]}]}
But I want this to be inserted in pretty format. I tried .toPrettyString() but got casting exception when try to put as json. I am trying the REST services for the first time, not sure where I am doing wrong. Please suggest me on this.
You should set following field in you Config.groovy.
grails.converters.default.pretty.print = true
This will pretty print for both the xml and json.
you could optionally set it up for xml or json only like below:
For json:
grails.converters.json.pretty.print = true
For xml
grails.converters.xml.pretty.print = true
A sample of Config.groovy entry is:
environments {
development {
grails.converters.json.pretty.print = true
}
}
Hope it helps!!!
For Grails 4, try this:
def json = x as JSON
json.prettyPrint = true;
log.info(json.toString())

how to use a map in a JsonBuilder? i.e. how to create dynamic, not static Json in grails?

creating hard coded json is easy, e.g.
String createJson(Person person, list<Account> accounts) {
def builder = new JsonBuilder()
def json = builder {
person person
accounts accounts
}
return builder.toPrettyString()
}
The above works, and produces something like this:
{
"person":{
username": "user"
"firstName": "test"
}
"accounts":[
{
"balance": "200829.00",
"currency": "CRD",
"id": 1,
}
]
}
The problem is we have a REST api, which returns JSON. Curently, we have a lot of duplicate code, as we can't find a generic way to generate different parts of the JSON api response and combine them together and render the result, ether by merging json strings, or by dynamically buidling the json from a map, e.g the following doesnt work:
String createJson(Map map) {
def builder = new JsonBuilder()
def root = builder {
map.collect { key, value ->
"$key" value
}
}
return builder.toPrettyString()
}
then calling it like this:
Person person = someMethodToGetAPerson()
List<Account> accounts = someMethodToGetAccounts(person)
Map map = ["person", person, "accounts", accounts]
String json = createJson(map)
render(status: 200, contentType: 'application/json', text: json)
However, this fails, with a stack overflow in the bowels of grails.
In addition, we have defined several json marshallers which must be used, e.g.
JSON.registerObjectMarshaller(Account) {
return [balance: formatter.format(it.balance)....
}
Any ideas?
What I could understand is you want to convert a map into JSON string. For that you can use grails.converters.JSON class. For example
Person person = someMethodToGetAPerson()
List<Account> accounts = someMethodToGetAccounts(person)
Map map = [person: person, accounts: accounts]
String json = new JSON(map).toString()
The toString() method also takes an boolean value for preety printing. And it should honor your registered marshallers

Use Jackson To Stream Parse an Array of Json Objects

I have a file that contains a json array of objects:
[
{
"test1": "abc"
},
{
"test2": [1, 2, 3]
}
]
I wish to use use Jackson's JsonParser to take an inputstream from this file, and at every call to .next(), I want it to return an object from the array until it runs out of objects or fails.
Is this possible?
Use case:
I have a large file with a json array filled with a large number of objects with varying schemas. I want to get one object at a time to avoid loading everything into memory.
EDIT:
I completely forgot to mention. My input is a string that is added to over time. It slowly accumulates json over time. I was hoping to be able to parse it object by object removing the parsed object from the string.
But I suppose that doesn't matter! I can do this manually so long as the jsonParser will return the index into the string.
Yes, you can achieve this sort of part-streaming-part-tree-model processing style using an ObjectMapper:
ObjectMapper mapper = new ObjectMapper();
JsonParser parser = mapper.getFactory().createParser(new File(...));
if(parser.nextToken() != JsonToken.START_ARRAY) {
throw new IllegalStateException("Expected an array");
}
while(parser.nextToken() == JsonToken.START_OBJECT) {
// read everything from this START_OBJECT to the matching END_OBJECT
// and return it as a tree model ObjectNode
ObjectNode node = mapper.readTree(parser);
// do whatever you need to do with this object
}
parser.close();
What you are looking for is called Jackson Streaming API. Here is a code snippet using Jackson Streaming API that could help you to achieve what you need.
JsonFactory factory = new JsonFactory();
JsonParser parser = factory.createJsonParser(new File(yourPathToFile));
JsonToken token = parser.nextToken();
if (token == null) {
// return or throw exception
}
// the first token is supposed to be the start of array '['
if (!JsonToken.START_ARRAY.equals(token)) {
// return or throw exception
}
// iterate through the content of the array
while (true) {
token = parser.nextToken();
if (!JsonToken.START_OBJECT.equals(token)) {
break;
}
if (token == null) {
break;
}
// parse your objects by means of parser.getXxxValue() and/or other parser's methods
}
This example reads custom objects directly from a stream:
source is a java.io.File
ObjectMapper mapper = new ObjectMapper();
JsonParser parser = mapper.getFactory().createParser( source );
if ( parser.nextToken() != JsonToken.START_ARRAY ) {
throw new Exception( "no array" );
}
while ( parser.nextToken() == JsonToken.START_OBJECT ) {
CustomObj custom = mapper.readValue( parser, CustomObj.class );
System.out.println( "" + custom );
}
This is a late answer that builds on Ian Roberts' answer. You can also use a JsonPointer to find the start position if it is nested into a document. This avoids custom coding the slightly cumbersome streaming token approach to get to the start point. In this case, the basePath is "/", but it can be any path that JsonPointer understands.
Path sourceFile = Paths.get("/path/to/my/file.json");
// Point the basePath to a starting point in the file
JsonPointer basePath = JsonPointer.compile("/");
ObjectMapper mapper = new ObjectMapper();
try (InputStream inputSource = Files.newInputStream(sourceFile);
JsonParser baseParser = mapper.getFactory().createParser(inputSource);
JsonParser filteredParser = new FilteringParserDelegate(baseParser,
new JsonPointerBasedFilter(basePath), false, false);) {
// Call nextToken once to initialize the filteredParser
JsonToken basePathToken = filteredParser.nextToken();
if (basePathToken != JsonToken.START_ARRAY) {
throw new IllegalStateException("Base path did not point to an array: found "
+ basePathToken);
}
while (filteredParser.nextToken() == JsonToken.START_OBJECT) {
// Parse each object inside of the array into a separate tree model
// to keep a fixed memory footprint when parsing files
// larger than the available memory
JsonNode nextNode = mapper.readTree(filteredParser);
// Consume/process the node for example:
JsonPointer fieldRelativePath = JsonPointer.compile("/test1");
JsonNode valueNode = nextNode.at(fieldRelativePath);
if (!valueNode.isValueNode()) {
throw new IllegalStateException("Did not find value at "
+ fieldRelativePath.toString()
+ " after setting base to " + basePath.toString());
}
System.out.println(valueNode.asText());
}
}