Hi I have a grails restful code. I do perfect a Json get and delete request.
My problem is:
I want to do a Put or post request with json but if I use a program to do that It has an error and I cant do it!
Here my code:
One class:
package catalogo.json
class Catalogo {
String nombre
String descripcion
String url
Set <Parametros>parametros =[]
static hasMany = [parametros:Parametros]
int numeroParametros = parametros.size()
}
And other class:
package catalogo.json
class Parametros {
String tipoParametro
String json
static constraints = {
tipoParametro(nullable:true)
json(nullable:true)
}
}
I don't know how to put my json in the request. Heres the error when I put it.
EXAMPLE:
I PUT POST request.
body application/json (or text/json is the same error) Charset-utf-8
{"descripcion": "bla", "nombre" : "lalala", "numeroParametros":3, "parametros":[{
"tipoParametro":"string", "json":"bla"}],"url":"http://www.google.com"}
And here the error:
Could not create new Catalogo due to errors:
grails.validation.ValidationErrors: 3 errors
Field error in object 'catalogo.json.Catalogo' on field 'descripcion': rejected value [null]; codes [catalogo.json.Catalogo.descripcion.nullable.error.catalogo.json.Catalogo.descripcion,catalogo.json.Catalogo.descripcion.nullable.error.descripcion,catalogo.json.Catalogo.descripcion.nullable.error.java.lang.String,catalogo.json.Catalogo.descripcion.nullable.error,catalogo.descripcion.nullable.error.catalogo.json.Catalogo.descripcion,catalogo.descripcion.nullable.error.descripcion,catalogo.descripcion.nullable.error.java.lang.String,catalogo.descripcion.nullable.error,catalogo.json.Catalogo.descripcion.nullable.catalogo.json.Catalogo.descripcion,catalogo.json.Catalogo.descripcion.nullable.descripcion,catalogo.json.Catalogo.descripcion.nullable.java.lang.String,catalogo.json.Catalogo.descripcion.nullable,catalogo.descripcion.nullable.catalogo.json.Catalogo.descripcion,catalogo.descripcion.nullable.descripcion,catalogo.descripcion.nullable.java.lang.String,catalogo.descripcion.nullable,nullable.catalogo.json.Catalogo.descripcion,nullable.descripcion,nullable.java.lang.String,nullable]; arguments [descripcion,class catalogo.json.Catalogo]; default message [La propiedad [{0}] de la clase [{1}] no puede ser nulo]
Field error in object 'catalogo.json.Catalogo' on field 'nombre': rejected value [null]; codes [catalogo.json.Catalogo.nombre.nullable.error.catalogo.json.Catalogo.nombre,catalogo.json.Catalogo.nombre.nullable.error.nombre,catalogo.json.Catalogo.nombre.nullable.error.java.lang.String,catalogo.json.Catalogo.nombre.nullable.error,catalogo.nombre.nullable.error.catalogo.json.Catalogo.nombre,catalogo.nombre.nullable.error.nombre,catalogo.nombre.nullable.error.java.lang.String,catalogo.nombre.nullable.error,catalogo.json.Catalogo.nombre.nullable.catalogo.json.Catalogo.nombre,catalogo.json.Catalogo.nombre.nullable.nombre,catalogo.json.Catalogo.nombre.nullable.java.lang.String,catalogo.json.Catalogo.nombre.nullable,catalogo.nombre.nullable.catalogo.json.Catalogo.nombre,catalogo.nombre.nullable.nombre,catalogo.nombre.nullable.java.lang.String,catalogo.nombre.nullable,nullable.catalogo.json.Catalogo.nombre,nullable.nombre,nullable.java.lang.String,nullable]; arguments [nombre,class catalogo.json.Catalogo]; default message [La propiedad [{0}] de la clase [{1}] no puede ser nulo]
Field error in object 'catalogo.json.Catalogo' on field 'url': rejected value [null]; codes [catalogo.json.Catalogo.url.nullable.error.catalogo.json.Catalogo.url,catalogo.json.Catalogo.url.nullable.error.url,catalogo.json.Catalogo.url.nullable.error.java.lang.String,catalogo.json.Catalogo.url.nullable.error,catalogo.url.nullable.error.catalogo.json.Catalogo.url,catalogo.url.nullable.error.url,catalogo.url.nullable.error.java.lang.String,catalogo.url.nullable.error,catalogo.json.Catalogo.url.nullable.catalogo.json.Catalogo.url,catalogo.json.Catalogo.url.nullable.url,catalogo.json.Catalogo.url.nullable.java.lang.String,catalogo.json.Catalogo.url.nullable,catalogo.url.nullable.catalogo.json.Catalogo.url,catalogo.url.nullable.url,catalogo.url.nullable.java.lang.String,catalogo.url.nullable,nullable.catalogo.json.Catalogo.url,nullable.url,nullable.java.lang.String,nullable]; arguments [url,class catalogo.json.Catalogo]; default message [La propiedad [{0}] de la clase [{1}] no puede ser nulo]
EDIT HERE MY CONTROLLER:
package catalogo.json
import grails.converters.JSON
class CatalogoController {
def index = {
switch(request.method){
case "POST":
def catalogo = new Catalogo(params.catalogo)
if(catalogo.save()){
response.status = 201 // Created
render catalogo as JSON
}
else{
response.status = 500 //Internal Server Error
render "Could not create new Airport due to errors:\n
${catalogo.errors}"
}
break
case "GET":
if(params.id){render Catalogo.findById(params.id) as JSON}
else{render Catalogo.list() as JSON}
break
case "PUT":
def catalogo = Catalogo.findById(params.catalogo.id)
catalogo.properties = params.catalogo
if(catalogo.save()){
response.status = 200 // OK
render catalogo as JSON
}
else{
response.status = 500 //Internal Server Error
render "Could not create new Catalogo due to errors:\n ${catalogo.errors}"
}
break
case "DELETE":
if(params.id){
def catalogo = Catalogo.findById(params.id)
if(catalogo){
catalogo.delete()
render "Successfully Deleted."
}
else{
response.status = 404 //Not Found
render "${params.id} not found."
}
}
else{
response.status = 400 //Bad Request
render """DELETE request must include the ID code
Example: /rest/catalogo/id
"""
}
break
}
}
def list = {
if(!params.max) params.max = 10
def list = Catalogo.list(params)
withFormat{
html{
return [catalogoList:list]
}
json{
render list as JSON
}
}
}
}
Thanks
Here is how it should be done in controllers:-
def index() {
//JSON Object is not bound to params it is bound to request in POST/PUT
def jsonObj = request.JSON
//You can also use JSON.parse() to get a JSON object if the request payload has JSON as string
//def jsonObj = JSON.parse(request)
//You will not be able to save the inner JSONArrays if you
// directly bind the jsonObj to the domain. in order to save
//convert them to the proper domain objects otherwise you would get validation errors for parametros
def catalogParams = [] as Set
jsonObj.parametros.each{
catalogParams << new CatalogParams(it)
}
//Set the domain back to the jsonObj
jsonObj.parametros = catalogParams
//Bind to catalog
def catalog = new Catalog(jsonObj)
//Synonymous to new Catalog(params) but here you cannot use params.
//Save
if (!catalog.save(flush: true)){
catalog.errors.each {
println it
}
}
render catalog
}
//Domain Classes:-
class CatalogParams {
String tipoParametro
String json
static constraints = {
tipoParametro(nullable:true)
json(nullable:true)
}
}
class Catalog {
String nombre
String descripcion
String url
Set<CatalogParams> parametros = []
static hasMany = [parametros: CatalogParams]
int numeroParametros = parametros.size()
}
REST Client:
How are you testing the REST WS? You should have a REST client to test the service? Or you can use REST console extension in Chrome to test your service. You can also use a grails plugin rest-client-builder to test your service. In basic terms, if you do not want any client implementation then atleast a script to test your service. HttpBuilder will be useful in this case:. Something like this is required to test your service
import groovyx.net.http.HTTPBuilder
def http = new HTTPBuilder('http://yourdomain.com/catalog/')
http.request(POST, JSON) {
requestContentType = ContentType.APPLICATION_JSON // coreesponding to application/json
body = ["descripcion": "bla", "nombre" : "lalala", "numeroParametros":3, "parametros":[{ "tipoParametro":"string", "json":"bla"}],"url":"google.com"]
response.success = { resp ->
assert resp.statusLine.statusCode == 200
}
}
Related
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
Hello I have created a RESTful web services which returns the responce in below format :
[
{"empId":1,"empName":"A"},
{"empId":2,"empName":"B"},
{"empId":3,"empName":"C"},
{"empId":4,"empName":"D"},
{"empId":5,"empName":"E"}
]
I have written the simple visualforce page to call the method named 'lookup' on button click action. My Apex class is given below.
public class REST {
public PageReference lookup()
{
string resp;
// Note this version of the API is only for the US
string endpoint ='http://localhost:8080/RESTfulExample/rest/json/metallica/get';
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
Http http = new Http();
req.setMethod('GET');
req.setEndpoint(endpoint);
try {
res = http.send(req);
} catch (Exception e) {
system.debug(LoggingLevel.Error, 'Error HTTP response code = '+res.getStatusCode()+'; calling '+endpoint );
return null;
}
resp = res.getBody();
JSONParser parser = JSON.createParser(resp);
// Parsing The JSON & set the list of values to the variables 'empid' & 'empname'
return null;
}
}
Can anyone help me how I can use JSON parser to parse the JSON and to store the values to the variables.
Thank You !!!
If you would like to use JSONParser here is an example from the Salesforce documentation on JSONParser(https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_json_jsonparser.htm):
public class JSONParserUtil {
#future(callout=true)
public static void parseJSONResponse() {
Http httpProtocol = new Http();
// Create HTTP request to send.
HttpRequest request = new HttpRequest();
// Set the endpoint URL.
String endpoint = 'https://docsample.herokuapp.com/jsonSample';
request.setEndPoint(endpoint);
// Set the HTTP verb to GET.
request.setMethod('GET');
// Send the HTTP request and get the response.
// The response is in JSON format.
HttpResponse response = httpProtocol.send(request);
System.debug(response.getBody());
/* The JSON response returned is the following:
String s = '{"invoiceList":[' +
'{"totalPrice":5.5,"statementDate":"2011-10-04T16:58:54.858Z","lineItems":[' +
'{"UnitPrice":1.0,"Quantity":5.0,"ProductName":"Pencil"},' +
'{"UnitPrice":0.5,"Quantity":1.0,"ProductName":"Eraser"}],' +
'"invoiceNumber":1},' +
'{"totalPrice":11.5,"statementDate":"2011-10-04T16:58:54.858Z","lineItems":[' +
'{"UnitPrice":6.0,"Quantity":1.0,"ProductName":"Notebook"},' +
'{"UnitPrice":2.5,"Quantity":1.0,"ProductName":"Ruler"},' +
'{"UnitPrice":1.5,"Quantity":2.0,"ProductName":"Pen"}],"invoiceNumber":2}' +
']}';
*/
// Parse JSON response to get all the totalPrice field values.
JSONParser parser = JSON.createParser(response.getBody());
Double grandTotal = 0.0;
while (parser.nextToken() != null) {
if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) &&
(parser.getText() == 'totalPrice')) {
// Get the value.
parser.nextToken();
// Compute the grand total price for all invoices.
grandTotal += parser.getDoubleValue();
}
}
system.debug('Grand total=' + grandTotal);
}
}
Although from what you say in your question I think it would be simpler to do JSON Deserialization.
Here is an example on how to do it:
Wrapper Class
public class EmployeeWrapper {
public Integer empId {get;set;}
public String empName {get;set;}
}
JSON Deserialization
String jsonContent = '[{"empId": 1,"empName": "A"}, {"empId": 2,"empName": "B"}, {"empId": 3,"empName": "C"}, {"empId": 4,"empName": "D"}, {"empId": 5,"empName": "E"}]';
List<EmployeeWrapper> employeeWrapperList = (List<EmployeeWrapper>)JSON.deserialize(jsonContent, List<EmployeeWrapper>.class);
System.debug(employeeWrapperList);
//Do actions to WrapperList
I'm creating a REST Mock that will receive as input a JSON request:
{
"infoSimIn":{
"idenficationSim":[
{
"imsi":123456789012345
}
]
}
}
How can i check if my JSON contains imsi Key, before returning the appropriate response ?
Thanks u..
Here is the script that shows you if imsi is present in the json
def str = """
{ "infoSimIn":{
"idenficationSim":[
{
"imsi":123456789012345
}
]
}
}"""
def json = new groovy.json.JsonSlurper().parseText(str)
def result = json.infoSimIn.idenficationSim.collect { it.keySet().contains('imsi')}[0]
assert result == true, 'json does not have imsi'
You can quickly check online Demo
EDIT: based on OP comment
Change from:
def str = ...
def json = new groovy.json.JsonSlurper().parseText(str)
To
def json = new groovy.json.JsonSlurper().parseText(mockRequest.requestContent)
EDIT : based on OP's comment and it works successfully unlike op complains null
And in the Mock service:
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())
In the following code i get the nullpointer exception only in some cases and the JSON is the same every time. How to resolve this
Error
errors.GrailsExceptionResolver - NullPointerException occurred when processing request: [POST] /school/sd/
Cannot set property 'school' on null object. Stacktrace follows:
Message: Cannot set property 'school' on null object
controller
def save() {
if (!requestIsJson()) {
respondNotAcceptable()
return
}
println request.GSON
def sInstance = new School(request.GSON)
println "got here"
if (sInstance.save(flush: true)) {
respondCreated sInstance
} else {
respondUnprocessableEntity sInstance
}
def resp = RestClientHelper.createExpGroup(sInstance)
}
In order to create Grails object from JSON it's easy to use special converter.
import grails.converters.JSON
.......
class Controller {
def doSomthing = {
def myDomain = new MyDomain(JSON.parse(params.myDomain))
//Save domain object
myDomain.save(flush:true)
}
}
Grails converter reference.