Scala, Json & Spring Boot Rest - json

I am building a Rest API using spring boot and Scala based on the below suggestion. I am successfully able to call the methods in Scala but the case class is not working the way it is designed.
When I try to create a Json using net.liftweb.json, I am getting additional string as "$outer":{}. I don't want this additional string in my output.
Note that the spring boot is expecting class instead of object. I suspect this could be an issue. Can you help me on this.
My case class looks like this:
case class BasicSrch(size: String, query: Match)
Erroneous output
{"$outer":{},"size":"10","query":{"$outer":{},"match":{"$outer":{},"_all":{"$outer":{},"query":"SNOW","operator":"and"}}}}
Expected Output
{"size":"10","query":{"match":{"_all":{"query":"VALLE","operator":"and"}}}}

If you are writing UTF-8 encoded JSON to the byte array or OutputStream then try jsoniter-scala: https://github.com/plokhotnyuk/jsoniter-scala
It will not serialize any other fields except those which are defined in a primary constructor of the case class.

Related

Serialize/deserialize a Dictionary with a comma-separated entry

I am developing a ASP.NET Core 3.1 website and I have data in a Dictionary<string, object> that I want to Serialize/Deserialize using Microsoft System.Text.Json (I am new to Json serialize/deserialize in fact). The data comes from a PostgreSQL DB query and one of the returned values is a comma-separated list of integers (converted to string) that results from the STRING_AGG function. The image below shows one of the entries of the Dictionary:
I serialize it using the following code. Please note that I have tried both Microsoft System.Text.Json and Newtonsoft.
jsonResult = Newtonsoft.Json.JsonConvert.SerializeObject(result);
//jsonResult = JsonSerializer.Serialize(result);
The data in the Dictionary should be deserialized according to the following class structure:
I use the following code:
//IEnumerable<SeccGralContenidoViewModel> seccGralContenido = JsonSerializer.Deserialize<IEnumerable<SeccGralContenidoViewModel>>(_seccGralContenidoRepository.Read());
IEnumerable<SeccGralContenidoViewModel> seccGralContenido = Newtonsoft.Json.JsonConvert.DeserializeObject <IEnumerable<SeccGralContenidoViewModel>>(_seccGralContenidoRepository.Read());
However, an exception is thrown when deserializing no matter if I use Newtonsoft or System.Text.Json:
I am originally using System.Text.Json namespace but I also tried using Newtonsoft. After analyzing a bit deeper, I see that the problem could be the way in which data is saved to the Dictionary but I have not found a workaround.
If you don't want to write a custom converter then the simplest solution is to introduce another property:
public string CategoriasContenidolds {get; set;}
private static char delimiter = ',';
[JsonIgnore]
public string[] CategoriasContenidolds_Collection
{
get => CategoriasContenidolds.Split(delimiter).Select(item => item.Trim()).ToArray();
set => CategoriasContenidolds = string.Join(delimiter, value);
}
The serializer will use the CategoriasContenidolds property during serialization and deserialization
You should use CategoriasContenidolds_Collection (or name whatever you want) in your business logic
By explicitly marking this property with JsonIgnore the serializer will ignore that
I could solve my issue by directly getting JSON formatted results from queries. PostgreSQL does an excellent job. This way I also avoid performing a 2-step process: first, getting the query result; second, serializing to JSON.

How to convert RealmResult to Json using Gson library

In this question How can I serialize a RealmObject to JSON in Realm for Java? The realm representative said that one can serialize realm object through GSON. Can you please explain it how?
I tried this.
RealmResults<Dog> myDogs=realm.where(Dog.class).findAll();
new Gson().toJson(myDogs);
But StackOverflowError occurred.
To make GSON serialization work with Realm you will need to write a custom JsonSerializer for each object that can be serialized and register it as a TypeAdapter.
You can see an example in this gist: https://gist.github.com/cmelchior/ddac8efd018123a1e53a
You get StackOverflow becouse of Gson based on reflection but managed object (RealmObjectProxy) have no real fields and fields of parent is nulls also some of proxy fields produses recursion in field type recognition of Gson it happens in $GsonTypes class.
To serialize RealmObject you can use one of this options:
Write your own adapter for every RealmObject childs which will takes data using getters.
Call realm.copyFromRealm(realmObject) before serialisation. It will looks like new Gson().toJson(realm.copyFromRealm(realmObject))
Use library based on 2nd option RealmSupportForGson
Hope it helps
The easier way is create a List<Dog> with RLMResult<Dog>, and then serialise this List with Gson.
After two days of bug resolve, I found this simple solution:
YourRealmObject realmObj = realm.where(YourRealmObject.class).findFirst();
if(realmObj != null) {
realmObj = realm.copyFromRealm(realmObj); //detach from Realm, copy values to fields
String json = gson.toJson(realmObj);
}

Grails, create domain object from json-string with has-many relation

I'm trying to parse a grails parameter map to a Json String, and then back to a parameter map. (For saving html form entries with constraint-violations)
Everything is fine as long as there is no hasMany relationship in the parameter-map.
I'm using
fc.parameter = params as JSON
to save the params as JSON String.
Later I'm trying to rebuild the parameter map and create a new Domain-Object with it:
new Foo(JSON.parse(fc.parameter))
Everything is fine using only 1:1 relationships (states).
[states:2, listSize:50, name:TestFilter]
But when I try to rebuild a params-map with multi-select values (states)
[states:[1,2], listSize:50, name:TestFilter]
I'm getting this IllegalStateException:
Failed to convert property value of type org.codehaus.groovy.grails.web.json.JSONArray to required type java.util.Set for property states; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [de.gotosec.approve.State] for property states[0]: no matching editors or conversion strategy found
I tried to use this, but without success:
JSON.use("deep") {
new Foo(JSON.parse(fc.parameter))
}
You can use JsonSlurper instead of the converters.JSON of grails, it maps JSON objects to Groovy Maps. I think this link also might help you.
Edit: Now, if the problem is binding the params map to your domain, you should try using bindData() method, like:
bindData(foo, params)
Note that this straightforward use is only if you're calling bindData inside a controller.
What seems to be happening in your case is that Grails is trying to bind a concrete type of List (ArrayList in the case of JsonSlurper and JSONArray in the case of converters.JSON) into a Set of properties (which is the default data structure for one-to-many associations). I would have to take a look at your code to confirm that. But, as you did substitute states: [1,2] for a method of your app, try another test to confirm this hypothesis. Change:
states:[1,2]
for
states:[1,2] as Set
If this is really the problem and not even bindData() works, take a look at this for a harder way to make it work using object marshalling and converters.JSON. I don't know if it's practical for you to use it in your project, but it sure works nicely ;)

Default for a missing field when deserializing Json with Jerkson

When parsing Json with the Jerkson library following the example in the docs:
case class Person(id: Long, name: String)
parse[Person]("""{"id":1,"name":"Coda"}""") //=> Person(1,"Coda")
If I try and deserialize Json that doesn't contain both the id and the name fields then an error is thrown saying they are needed. Is there a way of setting it up so that if the following Json for a Person was parsed:
{"id":2}
The name field could be defaulted to "John". (I thought this might be possible by setting a default in the parameter in the case class but no luck)
Check out this pull request I did for the Jerkson library. It adds support for case class default parameters.
Pay heed to user ksvladimir's comment, though, which I haven't had time to add to the pull request. (I'll update this answer when I do)

Convert JSON formated String to JsonObject with Jayrock

I have a request parameter in my ASP.NET app. that is in JSON format, and I was wondering if there is a good (quick and easy) way to convert a JSON string to a Jayrocks JsonObject, so I can easily extract key-value pairs without the need to manually parse the string?
Assuming json is the variable containing JSON text, use Jayrock.Json.Conversion.JsonConvert.Import(json). What you will get back in return is either a JsonObject, JsonArray, JsonNumber, System.String, System.Boolean or a null reference depending on the root JSON value in the source JSON text. If you know it is going to be a JSON object for sure then you can safely cast the return value or use JsonConvert.Import<JsonObject>(json).
I would discourage working against JsonObject directly unless you particularly depend on one of its features. You should just pretend the JSON object you get back is a dictionary; either IDictionary or IDictionary<string, object>. With the latest version for .NET Framework 4, you can also work with a JsonObject as a dynamic object.
I don't know Jayrock, but if you want to accept a JSON object as a parameter of Action in MVC2 than the easiest way to do it is by using JsonValueProviderFactory from Futures assembly.
It's part of System.Web.Mvc in MVC3.