error doing nested resource in grails - json

i am try to do nested resource call using angular and grails.
in my account domain i map domain this way:
example:
class Account {
static hasMany=[contacts:Contacts,users:User_BE];
}
and in contact domain
example:
class Contacts {
static belongsTo=[accounts:Account];
}
my json structure is like this:
{"accountType":"Single","traderwinkel":true,"lynxAgro":true,"contacts":[{"class":"com.crm.contacts","name":"abc"}]}
i am getting this error:
null id in com.crm.Contacts entry
and i am also try to send json without using array like this:
{"accountType":"Single","traderwinkel":true,"lynxAgro":true,"contacts":{"class":"com.crm.contacts","name":"abc"}}
but got same error like above.
and also i have used restfullcontroller:
class AccountController extends RestfulController {
static responseFormats = ['json', 'xml']
}
please suggest me how should i need to structure and send json data

Related

How do I render plain object as JSON, XML in Grails?

I have a controller (RestfulController) code similar to the following:
def doSomethingAwesome() {
Domain domainObject = prepareDomainObject()
//do something on the domain object
Model model = new Model(name: domainObject.name, description: domainObject.description)
respond model
}
As can be seen, I'm trying to respond with data wrapped inside a Model object. However, Model class is not a domain class; it's just a plain Groovy class. When I try to test this code in isolation, I get it to pass, but when I test it with all the other tests, I get GroovyCastException saying the object cannot be cast to JSON.
Some of the articles that came up of my searches suggest I put the model object inside a map then have that map get rendered. Something like:
render ['model': model] as JSON
However, this isn't how I'd like the response message to be. In addition, the XML message would look very different.
The Grails 2.4.3 demo project at https://github.com/jeffbrown/pogorespond demonstrates passing a POGO (not a domain class) to the respond method. https://github.com/jeffbrown/pogorespond/blob/1646c64fe2b37856fc87b64ae1cf5a6c4fd44cb1/grails-app/controllers/demo/DemoController.groovy contains the following:
package demo
class DemoController {
static responseFormats = ['json']
def index() {
def m = new Model(name: 'Some Name', description: 'Some Description')
respond m
}
}
class Model {
String name
String description
}

Grails: Defining a JSON custom marshaller as static method in domain

I'm using Grails 2.4.2. As can be seen here:
https://grails.org/Converters+Reference
You can create a static method in your domain with your custom marshaller to render the JSON in the controller. Like that:
Domain:
// a class to output in JSON
package com.sample
class User {
String login
String passwd
// JSON definition of the User object
static {
grails.converters.JSON.registerObjectMarshaller(User) {
return [
login: it.login
]
}
}
Then in your controller:
def user = new User(login:'bob', passwd:'1234')
render user as JSON
This is not working for me in my project. I render it and outputs as the default rendering (with class:"com.sample.User"...). But if I change something in the domain and the environment "reloads" it (recompiling), then the render is OK.
Of course, I want the custom marshaller code to be in the domain, and if it's possible with no more other code outside (BootStrap.groovy, resources.groovy...) etc, I know how to do custom marshaller the other way (like here: http://compiledammit.com/2012/08/16/custom-json-marshalling-in-grails-done-right/)
So... what i missed? Is it possible?

Grails - rendering UUID to JSON

I'm using UUID as generator for my domain classes. When I render domain objects as JSON, the id looks like the following:
"id":{"class":"java.util.UUID","leastSignificantBits":-7570618374586820490,"mostSignificantBits":126481566314875615}
Instead, I want it to look as simple as,
"id":"01c15a50-7ed5-4adf-96ef-c2b2fcb51876"
which is how it looks like when I render the domain objects to XML. How do I make it work this way?
It may help if you post your domain class, but my assumption is it's something like the following:
class MyDomain {
UUID id = UUID.randomUUID()
}
Unless you explicitly need to keep it as a UUID, I imagine this will render the JSON as you're expecting:
class MyDomain {
String id = UUID.randomUUID().toString()
}
Because I required the UUID class so that ORM would work between Grails and Oracle, I couldn't just make the id field a String.
So instead, I used a very basic JsonRenderer to override the default (troublsome) JSON rendering of a UUID object.
#CompileStatic
class UuidJsonRenderer extends DefaultJsonRenderer<java.util.UUID> {
UuidJsonRenderer() {
super(java.util.UUID)
}
void renderJson(java.util.UUID object, RenderContext context) {
super.renderJson(object.toString(), context)
}
}
And plugged it in as a bean the following in resources.groovy:
beans = {
// Custom Renderers
uuidJsonRenderer(UuidJsonRenderer)
}
(I think you could probably annotate the renderer and have an annotation processor do this part automatically, if that's your pleasure.)

Reflectively save domain class instances in Grails

The problem is as follows: I want to handle a POST request with JSON body. The body consists of an array of JSON Objects, without further nesting, i.e. simple HashMaps. All of these objects represent JSON-serialized domain classes from an Android Application, which will have their counterpart in my Grails app. I am thinking of parsing the JSON body, iterating through every element and saving each node as its corresponding domain class instance.
a) How should I save the instance? I am quite new to Grails/Groovy so please excuse any huge mistakes. Code so far is
public static Object JSONArray2Instances(String json, Class type) {
def slurper = new JsonSlurper()
def result = slurper.parseText(json)
//we only want to parse JSON Arrays
if (!(result instanceof JSONArray))
return null
result.each {
def instance = it.asType(type)
// now I need to save to domain class!
}
}
b) where do I place the corresponding code? Currently it is in /grails-app/src/groovy. Where do the tests go? (Since it is not a 'real' Grails component)
c) Is an intermediate command object more appropriate?
Your code should go in to the controller which is handling the request. Please take a look at
gson-grails plugin which has examples of how to serialize and deserialze objects and map them to domain objects. Please take a look at the grails basics where they talk about the conventions used in the grails application and the layout. There are good examples at grails site. Hope this helps
I solved my problem as follows, based on help provided by the comment from allthenutsandbolts. : (Grails-Gson plugin was not needed)
Let N2696AdminAction be the name of a Domain Class
in my controller:
class N2696AdminActionController extends RestfulController{
static responseFormats = ['json', 'xml']
def JSONHandlerService
N2696AdminActionController() {
super(N2696AdminAction)
}
#Override
#Transactional
def save(){
if (request!=null)
JSONHandlerService.instancesfromJSON(request.JSON)
}
}
then I delegate persisting to my service as follows
class JSONHandlerService {
def instancesfromJSON(Object request){
//we only want to parse JSON Arrays
if (!(request instanceof JSONArray))
return null
request.each {
def domainClass = Class.forName("${it.type}",
true, Thread.currentThread().getContextClassLoader())
def newDomainObject = domainClass.newInstance(it)
newDomainObject.save(failOnError:true, flush:true, insert: true)
}
}
}
type is a Json attribute which holds the full (package inclusive) name for my class. This way, I can save to multiple Domain Classes with the same POST request.

JSON output of a view in Grails

Ok, I have a very simple app created in Grails.
I have a generated domain class (Person) and its generated controller, using the automatic Grails scaffold:
package contacts
class PersonController {
def scaffold = Person
}
Now I'd like to get a JSON representation of a Person object.
Do I have to change the view or the controller? And how?
Thank you.
Add the following to your controller:
def list = {
params.max = Math.min(params.max ? params.int('max') : 10, 100)
def personList = Person.list(params)
withFormat {
html {
[personInstanceList: personList, personInstanceTotal: Person.count()]
}
json {
render personList as JSON
}
}
}
This should support both your scaffolding and the JSON output.
You can access the scaffolding as:
http://localhost:8080/contacts/person/list
You can access the Person list as json with:
http://localhost:8080/contacts/person/list?format=json
There are other ways to do it too, but I like doing it this way to leave the scaffolding around for testing.