Deep JSON serialization in Grails not working - json

I have an object structure like so:
class Message {
static mapWith="mongo"
static embedded = ['to', 'author', 'comments', 'tags']
ObjectId id
Set<ObjectId> to
Author author
String text
List<Comment> comments
Set<String> tags
Date postedOn
Date lastEditOn
}
class Comment {
Author author
String text
int thumbsUp = 0
int thumbsDown = 0
Date postedOn
Date lastEditOn
}
And the following code for serialization to JSON
render Message.findStreamFor( session.user, groups, 0, 20 ) as JSON
However, none of the embedded collections are being serialized. They are just missing. I've tried adding the following to my Config.groovy to make it deeply serialize by default:
grails.converters.json.default.deep=true
But that doesn't seem to change anything. I've seen the objects are populated from MongoDB in the debugger, but it just doesn't make it to the JSON serialized output. How can I fix this?
UPDATE
Ok I've figured out a bit more by debugging the code. Inside the DefaultGrailsDomainClass.getPersistentProperties() it doesn't return the collections as properties when called. And JSON serializer never visits them. On line 103 of DomainClassMarshaller is the call to getPersistentProperties which isn't returning all properties.
GrailsDomainClassProperty[] properties = domainClass.getPersistentProperties();
Seems like this is a bug! How has no one else ever found this?

You could to use GSON plugin. It didn't help me in a similar problem but it may help you.
This plugin was written to overcome nested object deserialization problem in standard Grails JSON converter, but it may also be better at serializing them.

Related

Array to string conversion in EasyAdmin 3 (Symfony 5)

I'm trying to display a json array on the EasyAdmin detail page. I read here Is there a way to represent a JSON field in EasyAdmin 3? that you can use ArrayField in EasyAdmin 3 to display a json array, which would make sense to me as that is the only field in EasyAdmin that could display it so I added it like this:
public function configureFields(string $pageName): iterable
{
return [
ArrayField::new('status', $this->translator->trans('form.label.status'))->onlyOnDetail(),
];
}
But it gives me this error:
An exception has been thrown during the rendering of a template ("Notice: Array to string conversion"). Do I need to add something else to it or does it not work at all?
change "status" to a multiplicity "statuses"
Worked for me with changing "print" to "prints"
I found a workaround that resolved the issue in my situation where I wanted just to show JSON on details page
So in your entity add a get function as an unmapped field as indicated in the official documentaiton
https://symfony.com/bundles/EasyAdminBundle/current/fields.html#unmapped-fields
for example
public function getJsonField() {
return json_encode($this->yourEntityJsonAttribute);
}
then in configureFields function in your CrudController add your field like this
TextAreaField::new('jsonField')->onlyOnDetail()
You can also read the json attribute and generate an HTML string in the getJsonField function then in configure field just add renderAsHtml in th field like this
TextAreaField::new('jsonField')->onlyOnDetail()->renderAsHtml()
Wish this suits your case too, Good luck

I can't parse a JSON with gson

i have this part of my json
POKEAPI get pokemons/sprite/version/
is from POKEAPI, the problem is in kotlin I can't use the '-' for creating a variable, for example: "var myvar-i = 0" and I need to create the variables exactly like the JSON for GSON mapping and the sprites in the JSON I need are like this
generation-i
generation-ii
etc..
in kotlin, I can't create variables with the '-'
enter image description here
someone help me, ¿How can I map that information in kotlin?
You can use the annotation #SerializedName
In your case it would be something like:
class Versions {
#SerializedName("generation-i")
var generation1: Generationgame? = null
...
}
More about the annotation can be found in the docs.

how to apply custom validation on json value

I have a json data coming via api. I have set of policies that I need to validate over coming json data.
For Example I have a json like
{
"users_id":"x",
"is_user_logged_in":"true",
"checkin_date":"2018-12-12",
"checkout_date":"2019-12-13"
}
Now I want to apply validation like checkin_date should be less than checkout_data or let say if is-user_logged_in is true then user_id should not be null.
I cant deserialize the json as i need to pass it to different application to consume
I am using Scala any idea how can i implement this. The catch is there can be multiple policies or rules i need to validate and i can only get the rules in runtime.
Thanks
Most easier way is to add validation to the default constructor and just use the JSON parser as a validator (no need to use parsed data):
import java.time.LocalDate
case class UserData(
user_id: Option[String],
is_user_logged_in: Boolean,
checkin_date: LocalDate,
checkout_date: LocalDate
) {
require(!is_user_logged_in || user_id.isDefined, "missing `user_id` for logged in user")
require(checkout_date.isAfter(checkin_date), "`checkout_date` should be after `checkin_date`")
}
For more complicated cases please consider to use some handy validation library, like:
https://github.com/jto/validation

Gson parse error, when the server response data is include an empty string(intent to be a int type), the error is Invalid double: ""

the server response data is like as
{
...
"number":"",
...
}
so when i use
Gson gson = new Gson();
gson.fromJson(data, obj.class);
the error will appear seems the String is null.
I've serach it with google and it seems custom GsonBuilder will solve this problem, but is it really and how?
Well, beacause the comment's hint, i changed my Google search wrods,and find this problementer link description here
This link will solve my problem.
So i write a primitive type typeadapter,and finally it works.
Try this, in place of "Object" use object of the class you need to convert to.
Type type= new TypeToken< Object>(){}.getType();
Object obj=new Gson().fromJson(json,type);

Why is GSON not parsing these fields properly? (FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)

I have a JSONArray of JSONObjects that I'm trying to parse with GSON. I'm using FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES. It's parsing correctly for most fields (so the FieldNamingPolicy is set correct), but I'm getting null returned for
{
"image_sq_48x48_url": "url1",
"image_sq_64x64_url": "url2",
"image_sq_96x96_url": "url3"
}
with field names
imageSq48x48Url
imageSq64x64Url
imageSq96x96Url
Maybe a better question would be what is the proper camelCase? I have also tried
imageSq48X48Url
imageSq48X48url
If I map with #SerializedName("image_sq_96x96_url") it parses/populates correctly.
Unfortunately those fieldnames in your JSON don't conform to what Gson looks for using that strategy.
If you create a POJO and serialize it, you can see what the issue is:
class MyPojo
{
String imageSq48x48Url = "hi";
}
The resulting JSON from Gson using that strategy is:
{"image_sq48x48_url":"hi"}
It doesn't consider/look at numeric digits as leading indicators / start of a "word".
If you rename the field to:
String imageSq_48x48Url;
It would work with your JSON example and that strategy.
Basically, you either need to create your own class that implements FieldNamingStrategy that will handle those JSON fieldnames the way you want, or do what you're doing with the #SerializedName annotation.