Can not deserialize instance of java.util.LinkedHashMap out of START_ARRAY token - jackson

Below mentioned is the JSON string, resultString:
{
"imageMaps": [{
"crc": "c2c4",
"flags": "0",
"length": "117384",
"index": 1,
"version": "1.1.90ea",
"status": ""
}, {
"crc": "7601",
"flags": "8",
"length": "117592",
"index": 2,
"version": "1.1.90ed",
"status": ""
}],
"complete": true,
"nextBootImageVersion": "",
"lastKnownGoodImageVersion": "1.1.90ed",
"runningImageVersion": "1.1.90ed"
}
I want to get the same converted to the object of class A:
public class A {
private boolean complete;
private String message;
private String lastKnownGoodImageVersion;
private String nextBootImageVersion;
private String runningImageVersion;
private Map<String, B> imageMaps;
private List<B> images;
private MacID macId;
}
I am trying to convert the json to object of class A using the code :
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
A a = objectMapper.readValue(resultString, A.class);
Code for class B is:
public static class B {
public String version;
public int flags;
public int crc;
public long length;
public String index;
public String status;
}
But getting the exception :
com.fasterxml.jackson.databind.JsonMappingException: Can not
deserialize instance of java.util.LinkedHashMap out of START_ARRAY
token

You declared property imageMaps as a Map<String, B> in your class, but in your JSON imageMaps is an array of B. The deserialization should work if you change imageMaps to images in your JSON.

Related

How to return ObjectNode from Controller in Micronaut?

I have following code
#Controller()
public class TestController {
#Get(value = "test", produces = MediaType.APPLICATION_JSON)
public MyDto fetch() throws Exception {
return new MyDto(
"test",
new ObjectMapper().readValue("{\"a\": 1}", ObjectNode.class)
);
}
#Serializable
#Data
public static class MyDto {
private final String name;
private final ObjectNode extraFields;
public MyDto(String name, ObjectNode extraFields) {
this.name = name;
this.extraFields = extraFields;
}
}
}
And I have an unexpected output on the client, extraFields object is empty
{
"name": "test",
"extraFields": [
[]
]
}
How to make Micronaut controller properly serialize com.fasterxml.jackson.databind.node.ObjectNode ?

Join the result of several microservice in a Mono

I try to develop a api with spring-cloud-gateway but it's not easy for me
My "microservice A" return an Mono. This Object contains a List of id "Object B"
My "microservice B" return an Flux
In my api-gateway, how can i aggregate in a Mono the result of the microservices ?
#Service
public class ServiceAClient {
private final WebClient webClient;
public ServiceAClient(WebClient.Builder builder) {
this.webClient = builder.baseUrl("lb://microservice-A/A/").build();
}
public Mono<ObjectA> getObjectA(String id){
return webClient
.get()
.uri("{id}" , id)
.retrieve()
.bodyToMono(ObjectA.class)
.onErrorResume(ex->Mono.empty());
}
}
#Service
public class ServiceBClient {
private final WebClient webClient;
public ServiceAClient(WebClient.Builder builder) {
this.webClient = builder.baseUrl("lb://microservice-B/B/").build();
}
public Flux<ObjectB> getListObjectB(List<Long> ids){
return webClient
.get()
.uri("{ids}" , ids)
.retrieve()
.bodyToFlux(ObjectB.class);
}
}
#Data
public class ObjectA {
private UUID id;
private String name;
private String description;
private Date start;
private Date end;
private List<Long> listIdObjectB;
}
#Data
public class ObjectB {
private Long id;
private String name;
private String localisation;
}
#Data
public class MyDto {
private UUID id;
private String name;
private String description;
private Date start;
private Date end;
private List<ObjectB> listObjectB;
}
#Service
#AllArgsConstructor
public class CombinedService {
private final ServiceAClient serviceAClient;
private final ServiceBClient serviceBClient;
public Mono<MyDto> getDetails(String id){
// return MyDto who join a Mono Service A an Flux service B
}
}
The desired result
{
"id": "2355e7eb-edf7-428c-b51b-ac06c146ed3c",
"name": "toto",
"description": "lorem ipsum",
"debut": 01/06/2022,
"fin": 10/06/2022,
"ListObjectB": [
{
"id": 1,
"name": "foo",
"localisation": "here"
},
{
"id": 2,
"name": "bar",
"localisation": "here"
}
]
}
Thank you in advance for your help
You can take it as a start point to understand a possible solution.
I highly recommend you to read about reactive streams(https://www.reactive-streams.org/) and spring-webflux(https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html).
Your CombinedService should looks like:
#Service
#AllArgsConstructor
public class CombinedService {
private final ServiceAClient serviceAClient;
private final ServiceBClient serviceBClient;
public Mono<MyDto> getDetails(String id) {
return serviceAClient.getObjectA(id)
.map(objectA -> {
final Flux<ObjectB> fluxB = serviceBClient.getListObjectB(objectA.getListIdObjectB());
final List<ObjectB> listObjectB = fluxB.toStream().collect(Collectors.toList());
final MyDto myDto = new MyDto();
myDto.setName(objectA.getDescription());
myDto.setDescription(objectA.getDescription());
myDto.setListObjectB(listObjectB);
//More setters, etc
return myDto;
});
}
}

How could I deserialize a JSON property into Java Object in Jackson

Given this response:
{
"data": {
"id": 38943,
"title": "Appetere Platonem Tempor Interesset Natum",
"description": "epicuri alia atqui",
"visibility": "PUBLIC",
"picture_url": null,
"logo_picture": null,
"owner_id": 51065,
"created_at": "2021-08-16T05:59:15.325Z",
"updated_at": "2021-08-16T05:59:15.325Z",
"counts": {
"subscriptions": 0,
"spots": 0,
"comments": 0,
"impressions": 0,
"respots": 0,
"attachments": 0
},
"user": {
"id": 51065,
"name": "Jon",
"screen_name": "jon",
"url": null,
"location": null,
"profile_picture": null,
"picture_url": null,
"header_picture": null,
"about": null,
"counts": {
"maps": 26
}
},
"map_settings": {
"editor_access": [
"can_none.map",
"can_create.spots",
"can_create.events",
"can_create.comments",
"can_create.attachments",
"can_create.collaborators"
],
"visitor_access": [
"can_none.map",
"can_none.spots",
"can_none.events",
"can_create.comments",
"can_create.attachments",
"can_none.collaborators"
],
"respotting_to_this_map": false
}
},
"meta": {
"code": 200
}
}
How could I deserialize the data property into a MapDTO like this
#JsonIgnoreProperties(ignoreUnknown = true)
#Data
#Builder
#ToString
#NoArgsConstructor
#AllArgsConstructor
public class MapDTO {
private Integer id;
private String title;
private String description;
private String visibility;
#JsonAlias("picture_url")
private String pictureUrl;
#JsonAlias("logo_picture")
private String logoPicture;
#JsonAlias("owner_id")
private Integer ownerId;
#JsonAlias("created_at")
private String createdAt;
#JsonAlias("updated_at")
private String updatedAt;
private MapCountsDTO counts;
#JsonAlias("map_settings")
private MapSettingsDTO mapSettings;
}
I've tried with a custom deserializer, but it looks cumbersome to get all the properties by name and then create a new MapDTO object based on those and the nested objects. If the structure changes I have to change the deserializer and the DTO itself. It would be easier to let Jackson do the deserialization starting from a given root. I'm using Jackson 2.12.4 through RestAssured 4.4.0. I'd like to avoid creating unnecessary wrapper classes.
Try to use jsonshema2pojo
This tool generates models for you.
All you need:
Copy and paste your JSON response to the window
Select on the radio group "Annotation style" radio button "Jackson 2.x"
Click on the "Preview" button
Profit.
Try this? https://json2csharp.com/json-to-pojo
// import com.fasterxml.jackson.databind.ObjectMapper; // version 2.11.1
// import com.fasterxml.jackson.annotation.JsonProperty; // version 2.11.1
/* ObjectMapper om = new ObjectMapper();
Root root = om.readValue(myJsonString), Root.class); */
public class Counts{
public int subscriptions;
public int spots;
public int comments;
public int impressions;
public int respots;
public int attachments;
public int maps;
}
public class User{
public int id;
public String name;
public String screen_name;
public Object url;
public Object location;
public Object profile_picture;
public Object picture_url;
public Object header_picture;
public Object about;
public Counts counts;
}
public class MapSettings{
public List<String> editor_access;
public List<String> visitor_access;
public boolean respotting_to_this_map;
}
public class Data{
public int id;
public String title;
public String description;
public String visibility;
public Object picture_url;
public Object logo_picture;
public int owner_id;
public Date created_at;
public Date updated_at;
public Counts counts;
public User user;
public MapSettings map_settings;
}
public class Meta{
public int code;
}
public class Root{
public Data data;
public Meta meta;
}

How to exclude Weld metadata from JSON object serialization

Assume the following REST resource:
#Path("/ActiveLeadTask")
//Also possible MediaType.APPLICATION_XML
#Produces(MediaType.APPLICATION_JSON)
public class ActiveLeadTask {
private #Inject ActiveLeadTaskBo activeLeadBo;
#GET
#Path("/getBo")
public ActiveLeadTaskBo getBo() {
return activeLeadBo;
}
}
////////////////////////////////////////////////////
#XmlRootElement
#XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
public class ActiveLeadTaskBo implements Serializable {
private static final long serialVersionUID = 1L;
private String firstName;
private String lastName;
private String phoneNumber;
private String phoneCountryCode;
private AtomicInteger accessCounterField = new AtomicInteger(0);
public ActiveLeadTaskBo() {
firstName = "test";
lastName = "test";
}
public int getAccessCounter() {
return accessCounterField.incrementAndGet();
}
public void setAccessCounter(int seed) {
accessCounterField.set(seed);
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
The REST response for getBo() JSON (but not for XML) returns the following:
{
"accessCounter": 1,
"firstName": "test",
"lastName": "test",
"metadata": {
"contextualInstance": {
"accessCounter": 2,
"firstName": "test",
"lastName": "test"
},
"instance": {
"accessCounter": 3,
"firstName": "test",
"lastName": "test"
}
}
}
The JSON response contains an additional "metadata" field - how can I configure the project to not generate it, or avoid generating it? The CDI container is Weld and the JSON serializer is provided by Yasson.
Two solutions are possible:
create a wrapper class, for example, ActiveLeadTaskBoInjectWrapper:
#Inject
ActiveLeadTaskBoInjectWrapper activeLeadBo;
activeLeadBo.getInstance();
workaround Weld specifics:
#Inject
Foo foo;
public void doSomething() {
if (foo instanceof WeldClientProxy) {
// foo is a proxy
((WeldClientProxy)foo).getMetadata().getContextualInstance()
} else {
// not a proxy
}
}
Depends on what JSON processing framework is used in your REST endpoint. For jsonb-api (jsr367) the only possible solution is to implement javax.json.bind.config.PropertyVisibilityStrategy to exclude generated properties from processing.

VB.NET newtonsoft list

Simple problem but seems i cant find a solution.
I have a json reader that needs a json like this :
[
{
"name": "name",
"ip": "0.0.0.0"
},
{
"name": "name",
"ip": "0.0.0.0"
}
]
I created a class on vb like this :
Public Class main_object
Public e As New List(Of _subObject)
Public Class _subObject
Public name As String
Public ip As String
End Class
End Class
My problem is that the output starts with
{
"e"[
mylist
]
}
Any solutions?
try this:
Public Class _subObject
Public name As String
Public ip As String
End Class
dim e As New List(Of _subObject)
dim x as new _subObject
x.name = "name"
x.ip= "0.0.0.0"
e.add(x)
e.add(x)
Dim jsonString As String = JsonConvert.SerializeObject(e, Formatting.Indented)
and you will get this in jsonString
[
{
"name": "name",
"ip": "0.0.0.0"
},
{
"name": "name",
"ip": "0.0.0.0"
}
]