Deserialize a JSON object with support for embedded associations - grails

Is there an easy way to deserialize a JSON string to a domain class with support of embedded association; belongsTo and hasMany
{
name: "Customer",
contact: {
name: "Contact"
}
}
class Customer {
name
Contact contact
}
class Contact {
String name
static belongsTo = [customer:Customer]
}
in my controller I would like to do the following
def save() {
def customer = new Customer(request.JSON)
customer.save();
}
Now i'm forced to do
def save() {
def contact = new Contact(request.JSON.contact);
def customer = new Customer(request.JSON);
customer.contact = contact;
customer.save();
}

Have you tried using JsonSlurper?
Example usage:
def slurper = new JsonSlurper()
def result = slurper.parseText('{"person":{"name":"Guillaume","age":33,"pets":["dog","cat"]}}')
assert result.person.name == "Guillaume"
assert result.person.age == 33
assert result.person.pets.size() == 2
assert result.person.pets[0] == "dog"
assert result.person.pets[1] == "cat"
Ref: http://groovy.codehaus.org/gapi/groovy/json/JsonSlurper.html
you can try this
Test test
def result = new JsonSlurper().parseTest('yourString')
test = result
Try this will work.

Related

Looking for nested object existance

class Car {
String carname
}
class Factory {
Car car
String factoryname
}
How can I check if an object Factory with factoryname == "Kia", carname == "newmodel" exists?
You could use createCriteria() method and alias.
def cName = 'newmodel'
def fName = 'Kia'
def objects = Factory.createCriteria().count() {
createAlias('car', 'c'),
eq('c.carname', cName)
eq('factoryname', fName)
}
boolean isThere = objects

Grails, gorm. Find child by parent and parent by child

For example, I've parent class Author:
class Author {
String name
static hasMany = [
fiction: Book,
nonFiction: Book
]
}
and a child class Book:
class Book {
String title
static belongsTo = [author: Author]
}
I've done some records to Author using:
def fictBook = new Book(title: "IT")
def nonFictBook = new Book(title: "On Writing: A Memoir of the Craft")
def a = new Author(name: "Stephen King")
.addToFiction(fictBook)
.addToNonFiction(nonFictBook)
.save()
How can I found child-class record by parent and parent-class record by child?
In my opinion, this is not the best way to model your data. I would do it like this.
class Author {
String name
static hasMany = [books: Book]
}
class Book {
String title
BookTypes bookType
static belongsTo = [author: Author]
}
enum BookTypes {
FICTION,
NON_FICTION
}
Then, you can do lookups like
def author = Author.get(1)
def nonFictionByAuthor = Book.findAllByAuthorAndBookType(author, BookTypes.NON_FICTION)
You could also just do something like this...
def author = Author.get(1)
def fictionBooks = author.books.findAll { it.bookType == BookTypes.FICTION }
And then inversely:
def fictionBook = Book.findByTitleAndBookType('Title001', BookTypes.FICTION)

Grails search from one to many is not working

Here are my domain class,
class Company {
String name
static hasMany = [groups:CompanyGroup]
}
class CompanyGroup{
String name
static belongsTo = [company:Company]
}
I receive params that contain name of CompanyGroup and I want to get the result of company that have the CompanyGroup found.
I did like this,
def groupList = account.companies.groups.flatten()
def groupResult = groupList.findAll{
it.name ==~ /(?i).*${params.keyword}.*/
}
I got the Companygroups that have name from params.key from above code. So I want to render company list that have these group like this,
def com = Company.withCriteria{
eq("groups", groupList)
}
render [companies : com]
It doesn't work!
def com = Company.withCriteria{
inList("groups", groupList)
}

Field values rendered null when using HTTP GET call in grails

This is domain class of Person :
package com.sample
class Person {
String id
String name
Integer age
Address address
static hasMany = [pets:Pet, alias: String, aliases : Alias]
static mapWith = "mongo"
static constraints = {
address nullable:true
pets nullable :true
}
}
This is the domain class of Address :
package com.sample
class Address {
String address
static mapWith = "mongo"
static constraints = {
address maxSize: 1000
}
}
This is ShowPerson method in PersonController:
def showPerson(String name,String age){
if(Person.findByAgeAndName(age,name) != null) {
render Person.findByAgeAndName(age,name) as JSON
}
else {
def addobj = new Address(address: "kondapur")
addobj.save(flush:true)
def pet1 = new Pet(name : "Dog", breed : "A")
pet1.save(flush:true)
def alias1 = "ALIAS1"
def alias2 = "ALIAS2"
def list = ["A"]
def aliases1 = new Alias(aliasname : [list])
aliases1.save(flush:true)
def person = new Person(name : name, age : age, address : addobj, pets : [pet1], alias : [alias1, alias2], aliases : [aliases1])
person.save()
render person as JSON
}
}
Initially there are no persons in DB(which impliesPerson.findByAgeAndName(age,name) == null) Hence it creates a new object and saves it in database). So when I click on the url
> http://localhost:8080/TestJson/showPerson/sample/23
The output now is :
Now when I reclick on the same url (implies Person.findByAgeAndName(age,name) != null) Hence it gets from the database):
The output now is :
In database the address is saved as :
In database the person is saved as :
Can someone tell me how can I get the address (encircled in red) as not null and get the corresponding value when I try to get a saved object from database (i.e in this case kondapur and not null)
Grails JSON marshaller by default doesn't add nested classes, you have to add one line of code:
def showPerson(String name,String age){
JSON.use('deep')// <============================== Add this line
if(Person.findByAgeAndName(age,name) != null) {
render Person.findByAgeAndName(age,name) as JSON
}
else {
def addobj = new Address(address: "kondapur")
addobj.save(flush:true)
def pet1 = new Pet(name : "Dog", breed : "A")
pet1.save(flush:true)
def alias1 = "ALIAS1"
def alias2 = "ALIAS2"
def list = ["A"]
def aliases1 = new Alias(aliasname : [list])
aliases1.save(flush:true)
def person = new Person(name : name, age : age, address : addobj, pets : [pet1], alias : [alias1, alias2], aliases : [aliases1])
person.save()
render person as JSON
}
}

grails domain dirtyPropertyNames for child object

def names = domain.dirtyPropertyNames
for (name in names) {
def originalValue = domain.getPersistentValue(name)
def newValue = domain."$name"
}
But if i have a relation of 1-1 with other domain
how can i access dirtyPropertyNames for that other domain
def dirtyProperties = domain?.otherDomain?.dirtyPropertyNames
for (name in dirtyProperties ) {
def originalValue = domain?.otherDomain?.getPersistentValue(name)
def newValue = domain?.otherDomain?."$name"
}
But i am getting
No such property: dirtyPropertyNames for class: otherDomain
This seems not to be an issue when tested against Grails 2.2.4 and 2.3.0.
How have you tailored the 1:1 relationship?
Here is a sample, hope that helps:
class Book {
String name
String isbn
static hasOne = [author: Author]
}
class Author {
String name
String email
Book book
}
//Save new data
def book = new Book(name: 'Programming Grails', isbn: '123')
book.author = new Author(name: "Burt", email: 'test', book: book)
book.save(flush: true)
//Sanity check
println Book.all
println Author.all
//Check dirty properties of association
def book = Book.get(1)
book.author.name = 'Graeme'
def dirtyProperties = book?.author?.dirtyPropertyNames
for (name in dirtyProperties ) {
println book?.author?.getPersistentValue(name) //Burt
println book?.author?."$name" //Graeme
}
Although, wrt Grails 2.3.0 you can persist a 1-1 relation as done below unlike above:
def author = new Author(name: "Burt", email: 'test')
def book = new Book(author: author, name: 'PG', isbn: '123').save(flush: true)

Resources