Getting JSON as string to a model object with Jersey - json

We're currently using Jersey 1.5.1 + Spring for handling JSON requests, and the request structure looks something like this:
{
"id": 34324242,
"foo": "bar",
"info": {
"infofield1": "some value",
"infofield2": "some other value",
"infodetails": {
"details1": "aaaa",
"details2": "bbbb"
}
}
}
The Java class to which this request would map (ideally) looks like this:
#XmlRootElement
public class FooBarRequest {
public Integer id;
public String foo;
public String info;
}
The idea is, that we want to get "info" as plain json string (not parsed to a any java object structure) to store it directly to DB as a BLOB. This doesn't seem to work out-of-a-box for Jersey 1.5.1, we are currently trying to upgrade to Jersey version 1.6, but maybe you have some tips on how to do that?
Maybe there is a ready XmlAdapter, which would perform something like this for us?
If not, does anyone know, how to write one for this particular case?

If you don't want to parse JSON into java, you should simply use a JSON parser directly on the input.

Related

What is the ideal way to JSON.stringify in Terraform?

I'm working on my first Terraform project and I'm looking for the best way to stringify a JSON object. The resource I'm defining has a parameter that expects a JSON string. JSON structure is:
"document": {
"tag": "String Title",
"response": "There's a string response and perhaps a price like $[XX.XX]."
}
}
I don't think jsonencode or jsondecode do this. I could stringify them in advance but that isn't scalable in this case. I wasn't sure if I could do this with JavaScript or another language alongside Terraform, or if there's a function in HCL that will do it.
jsonencode in Terraform is exactly equivalent to JSON.stringify with only one argument in JavaScript.
For example, if you need to assign a string containing a JSON object to an argument called something_json, you could do that like this:
something_json = jsonencode({
document = {
tag = "String Title"
response = "There's a string response and perhaps a price like $[XX.XX]."
}
})
The above would set something_json to a minified version of the following JSON:
{
"document": {
"tag": "String Title",
"response": "There's a string response and perhaps a price like $[XX.XX]."
}
}
Terraform does not have an equivalent of the optional replacer and space arguments in JavaScript's JSON.stringify:
An equivalent of replacer isn't needed in Terraform because all possible values in the Terraform language have a defined JSON equivalent as described in the table in the jsonencode documentation.
space is for generating non-minified JSON; Terraform does not offer any way to do this because it is focused on generating JSON for machine consumption and so prefers to generate the most compact representation possible.

Ktor: How to serialize/deserialise JSON-API (vnd.api+json)

I'm looking to rewrite a spring javafx application in Kotlin using Ktor. I am new to both Spring and Ktor.
I'm having trouble using Ktor to figure out how to approach serialization and deserialisation of POJOs. (These POJOs are part of a common library).
The API I'm trying to serve requests to with Ktor uses:
Hibernate ORM as ORM mapper
Elide with RSQL filters to serve JSON-API conform data
For example "data/event" would return:
{
"data": [
{
"type": "event",
"id": "15b6c19a-6084-4e82-ada9-6c30e282191f",
"attributes": {
"imageUrl": null,
"name": "some text",
"type": "NUMERIC"
}
}, // and more event objects
]
}
Looking at the codebase in the spring application, it looks like they are using a RestTemplate to deserialise the above into an Event class (which only has an id, imageUrl, name and type as variables). Spring seems to automatically know how to get a POJO from JSON-API.
How can I do the same with Ktor? I tried the simplest:
val response = client.request<List<Event>>("data/event")
With the serialiser as gson:
install(JsonFeature) {
serializer = GsonSerializer()
}
But this results in a list of Event objects with none of their variables correctly set.
I have to make a wrapper class:
data class MyWrapper(val data: List<Event>)
And with that it will populate the list with the objects id set correctly, but none of the other attributes. So by default it looks like Ktor isnt configured for JSON-API. How can I change this?
I believe JSON:API is not supported out of the box. You need to write your own serializer, or use another wrapper class:
class JSONAPI<T>(val type: String, val id: String, val attributes: T)
data class MyWrapper(val data: List<JSONAPI<Event>>)
The problem here is that all fields in Event except of id will be filled. So you will need to adjust deserialization result:
val response: List<Event> = client.request<MyWrapper>("data/event").data.filterNotNull().map { it.attributes.copy(id = it.id) }

JSON deserialization error in WebApi with array

I'm posting the following JSON payload from a JavaScript Angular app to a webapi service:
{Notes: "test", Ids: [606, 603]}
this.http.post(url, {"Notes": "test", "Ids": [606,603]}, options)
I'm attempting to deserialize this into a .net Dictionary like:
[HttpPost]
public IHttpActionResult Test(Dictionary<string,string> formData)
{
}
(I've tried to add the [FromBody] decorator too).
If I don't include the array, this works fine. But with the array, I get a couple of parse error:
Unexpected character encountered while parsing value: [. Path 'Ids', line 1, position 23.
Invalid JavaScript property identifier character: ]. Path 'Ids', line 1, position 30.
The "JSON" you're posting is not valid JSON - you can use a tool like JSONLint to validate your JSON.
The correct JSON syntax for your data is:
{
"Notes": "test",
"Ids": [606, 603]
}
Also - the method takes a Dictionary<string,string> object. Your array is not a string, and the controller will therefore fail while trying to deserialize the array into a string.
My suggestion is to create a model, which the controller method should receive. Like this:
[HttpPost]
public IHttpActionResult Test(YourModel data)
{
}
class YourModel
{
public string Notes {get;set;}
public int[] Ids {get;set;}
}
Using this code, the controller will deserialize your JSON (when you have corrected the JSON syntax problems) into an instance of YourModel.

Is this json badly constructed?

The following json text is the result of a call to eBay's search API.
Q: Is this json badly constructed? (It's technically, correct - so that's not what I'm referring to)
By that I mean, notice how -every value- is inside an array? instead of just being a "key" : "value" ?
eg.
"ack": [
"Success"
],
or
"version": [
"1.12.0"
],
etc..
Now, before you answer "well, maybe each key has multiple result values" .. I'm pretty sure most of them can't.
(this json schema is really making my life a pita. yes, it's easy to make each POCO property a List<string> but it's the point of it all!)
References: Here's the office eBay API documention for this endpoint
After reading the documentation, I understand eBay's approach, but I find it poor in terms of client side deserialisation. For example, the benefit of an array value for the ack property is that the value could also contain a warning, e.g.:
{
"ack": [
"Success",
"Warning"
]
}
However, a list of strings is not ideal for client side processing (e.g. in C#, bool hasWarning = pocoList.Contains("Warning"); doesn't strike me as completely foolproof). I'd rather have a response such as:
{
"ack": {
"result": "Success",
"warning": null
}
}
Then with my deserialised POCO, given that the value of warning is still a string, I could write this:
[DataContract]
public class Ack
{
[DataMember(Name="result")]
public string Result { get; set; }
[DataMember(Name="warning")]
public string Warning { get; set; }
[IgnoreDataMember]
public bool HasWarning
{
get { return !string.IsNullOrEmpty(Warning); }
}
}
This would allow me to replace my previous LINQ query with bool hasWarning = ack.HasWarning;.
There are definitely places where use of arrays is completely unnecessary. The docs describe the version property as "the release version that eBay used to process the request", thus I would return this as a single string. The array would only make sense if it was a versions property (e.g. for identifying all versions of the backend that support a specific request).
I've definitely seen worse JSON responses, but there are places where the APIs should ideally be returning a JSON object or a single value.
I normally use this tool for see if a JSON is good constructed:
http://json.parser.online.fr/
In your case, is not correct. You should store the data by Keys and Values.

GWT Autobean - how to handle lists?

I have been trying to evaluate GWT Autobean feature to decode/encode JSON object to domain objects for REST calls.
Following the example : http://code.google.com/p/google-web-toolkit/wiki/AutoBean#Quickstart
I was able to convert a singular JSON object to a domain object:
AutoBean<Person> personBean = AutoBeanCodex.decode(factory, Person.class, JsonResources.INSTANCE.json().getText());
where JsonResources.INSTANCE.json() is returning a JSON string.
However, I haven't been successful to convert a list of Person objects from JSON.
It would be helpful, if anyone has an example of this?
Thanks!
Well the only way I can think of is to create a special autobean, which will have List<Person> property. For example:
public interface Result {
void setPersons(List<Person> persons);
List<Person> getPersons();
}
And example json string:
{
persons:[
{"name":"Thomas Broyer"},
{"name":"Colin Alworth"}
]
}
UPDATE:
Workaround when input JSON is an array ( as suggested by persons[0] in comments).E.g. JSON looks like this:
[{"name":"Thomas Broyer"},{"name":"Colin Alworth"}]
And parsing code looks like this:
AutoBeanCodex.decode(factory, Result.class, "{\"persons\": " + json + "}").getPersons();