Map of Instant to list of objects - jackson serialization/deserialization - json

I have a spring boot app and the following DTO class:
public class CarDto {
private Map<Instant, List<CarModelDto>> dateToCarModels = new HashMap<>();
// getters/setters omitted for brevity
}
When I make a call from postman it looks like this:
{
"dateToCarModels": {
"1544612555": [{
<obj1>
},
{
<obj2>
}],
"1544785355": [{
<obj1>
}]
}
}
It gives me the following error:
JSON parse error: Cannot deserialize Map key of type
`java.time.Instant` from String "1544612555": Failed to deserialize
java.time.Instant: (java.time.format.DateTimeParseException) Text
'1544612555' could not be parsed at index 0; nested exception is
com.fasterxml.jackson.databind.exc.InvalidFormatException: (...)
That is understandable as I have Instant as a key map (and pass String in json - since JSON keys must be strings).
Is there any better way to fix it than writting own key serializer/deserializer ?

Related

Explicit type for List in JSON-Response in REST API

Getting explicit java.util.ArrayList in JSON responses for lists
Hi,
I'm writing a REST API using Kotlin and noticed that when I'm creating a class returning a list like this:
data class TestClass( var test: List<String> = listOf() )
This is the JSON I'm getting in response, with explicit ArrayList as type:
{ test": [ "java.util.ArrayList", [] ] }
Is it possible to not get the java.util.ArrayList in the JSON response?

How to model key:value object in the ProtoBuf

I have to compose a protobuf message which should have object with N key:value pairs.
{ "0xc02aaa39b223fe8d4a0e5c4f27ead9083c756cc2": "73185315951404654", "0x111111111117dc0aa78b770fa6a738034120c302": "90483392540197705773", "0xdac17f958d2ee523a2206206944597c13d831ec7": "2599292593", "0x6b175474e89094c44da98b954eedeac495271d0f": "2887251922547121516", "0xa0b86991c6218b36c1d19d224a2e9eb0ce06eb48": "1995436171", "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599": "152669472", "0x0bc529c00c6401aef6d220be8c6ea1667f6ad93e": "78565917807540502", "0x888888888889c00c67689029d7856aac1065ec11": "10015330752170299581" }
Is there a way to compose this JSON?
I tried to use map:
message Reply { map<string, string> balances = 1; }
but ended up with this error message:
Object literal may only specify known properties, and '0xc02aaa39b223fe8d4a0e5c4f27ead9083c756cc2' does not exist in type 'Reply'.

How do I correctly deserialize json that consists of a list item that includes another object?

The client I am using returns json like this:
[
{
"source": "ANY"
}
]
That is, the element of the array that the object is in.
I'm trying to make a request like this:
restTemplate.postForObject<AbcdResponse>(
"/address",
listOf(value).let { JsonHttpEntity(it) }
)
data class AbcdResponse(
val obj: AbcdObject
)
data class DaDataAddress(
val source: String?
)
But I get the HttpMessageNotReadableException exception:
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `com.app.client.abcd.domain.AbcdResponse` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `com.app.client.abcd.domain.AbcdResponse` out of START_ARRAY token
at [Source: (ByteArrayInputStream); line: 1, column: 1]
How can I deserialize the response correctly?
As you probably noticed, the response as a whole is a JSON array. You can tell by the square brackets [ ... ] surrounding the whole thing.
Because of this, you cannot deserialize it as an object (such as AbcdResponse). What you should do instead is use List<DaDataAddress> instead of AbcdResponse.
You don't really need AbcdResponse. What you need is to use a ParameterizedTypeReference as follows while calling the service:
restTemplate.exchange("/address",
HttpMethod.POST,
listOf(value).let { JsonHttpEntity(it) },
ParameterizedTypeReference<List<DaDataAddress>>() {})
The reason is that the service that you are calling is returning a JSON array of JSON objects.

How to Deserialize a JSON and serialize a specific String value pair as different JSON?

The Json body I want to deserialize is something like below
{
"status": "OK",
"place_id": "07e0a63d862b2982e4c4b7e655f148d2",
"scope": "APP"
}
Below is the Json body I want to build from above Json after deserializing it
{
"place_id": "07e0a63d862b2982e4c4b7e655f148d2"
}
Because your JSON data appears to be rather small you could use Gson's JsonParser.parseString(String) method to parse the data into an in-memory representation, then copy the relevant JSON object member to a new JsonObject and serialize that to JSON using Gson.toJson(JsonElement):
JsonObject original = JsonParser.parseString(json).getAsJsonObject();
JsonObject copy = new JsonObject();
// Might also have to add some validation to make sure the member
// exists and is a string
copy.add("place_id", original.get("place_id"));
String transformedJson = new Gson().toJson(copy);
If this solution turns out to not be efficient enough for you, you could also have a look at JsonReader and JsonWriter.

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.