Spring Boot: Problems deserializing JSON objects. Change property names - java

I'm developing a back-end web application using Spring Boot with Java and I have the following problem:
A REST service returns me the following JSON:
{
"cap":"98888"
}
This is my JAVA class which models the output based on the content:
#NoArgsConstructor
#Data
public class MyObject {
private String cap;
}
I would like to change the field name for MY service to return the following JSON:
{
"CAP":"98888"
}
In my JAVA code, I make the call via RestTemplate, like this:
return restTemplate.postForObject(uriBuilder.build().toUri(), new HttpEntity<>(request, headers), MyObject.class);
I've tried to use tons of stuff with Jackson, including #JsonProperty, like this:
#NoArgsConstructor
#Data
public class MyObject {
#JsonProperty("CAP")
private String cap;
}
But the result is this:
{
"CAP":null
}
As if it no longer matches the original name of the property. In practice I can only get an output with correct value but original field name (WHICH I DON'T WANT) or an output with the name of the field I want (i.e. CAP) but with a null value.
Which is the right way to rename properties with Spring annotations?

Related

Return an array of objects with fieldName in spring boot

I am new to springboot. My requirement is as below.
I have carModel class as below.
#Data
public class CarModel {
private modelName;
private available;
}
Now I have a rest endpoint that returns the list of objects. So the resource looked something like this.
#GetMapping("/models")
public List<CarModel> getModels(){
//Resource Body
}
But this return an array of objects in json, with no field name. But I need the the json , something like this:
{ "AllModels" : [ { "modelName" : "Ferrari", "available" : "Yes"} , {"modelName": "Tesla" , "available" : "Yes"} ]
How can I do this in spring boot? I do know of a solution by defining one more wrapper class with list of CarModel objects in it. But is there any better way of doing it(Something like any annotations, etc.,)
Thanks!
You can use ResponseEntity method that is already there available in Spring MVC. Would something like this work for you?
#GetMapping("/models")
public ResponseEntity<List<CarModel>> getCars() {
List<CarModel> carModels = service.methodThatReturnsListOfCarModels();
return ResponseEntity.ok().body(new HashMap<>(){{put("AllModels", carModels);}});
}

Jackson cannot construct instance with one parameter constructor

I am using Spring Boot to create a web application. One of the endpoints expect a json object having one property, i.e. studentId. I am using DTO like my other functions to capture the payload.
#PostMapping("/courses/{id}/students")
public SuccessResponse<Void> addEnrolls(#PathVariable Long id, #RequestBody StudentIdPayload payload) throws HandledException {
courseService.addEnrolls(id, payload.getStudentId());
return success(HttpStatus.OK);
}
#Data
#AllArgsConstructor
public class StudentIdPayload {
private Long studentId;
}
But when I tried to post the endpoint with json body {"studentId":1}, I got the following error :
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `org.bimoadityar.univms.dto.input.StudentIdPayload` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
While it works if I post using just the value 1.
How can I get it to work with the object payload?
Interestingly, when I add another property to the StudentIdPayload, such as String placeholder, it works as intended, although this solution feels hacky.
Considering https://github.com/FasterXML/jackson-databind/issues/1498, it seems that this is the intended behavior.
For my particular case, I am satisfied with adding the #JsonCreator to my constructor.
#Data
#AllArgsConstructor(onConstructor = #__(#JsonCreator))
public class StudentIdPayload {
private Long studentId;
}
By default, deserialization requires no-args constructor, so add #NoArgsConstructor:
#Data
#AllArgsConstructor
#NoArgsConstructor
public class StudentIdPayload {
private Long studentId;
}
see also:
Annotations: using custom constructor

I want one of the String member variables in my Spring Boot Java #Entity model class to show up as an actual JSON object when sent to the client side

I want one of the String member variables in my Spring Boot Java #Entity model class to show up as an actual JSON object when sent to the client side, but I am not sure how this is possible
I have this #Entity class in Spring Boot :
#Entity
#Data
public class A {
#JsonProperty
private String value
}
That "value" in the class A is supposed to be a JSON object, but I had to keep it in string type or it won't save into the DB by JPA.
When the controller returns this model object to the client side, the "value" in the JSON string will show up as a full string instead of a JSON struct.
i.e.
This shows up
{
"value": "{\"another_value\":\"1234\"}"
}
instead of
{
"value": {"another_value":"1234"}
}
Is there some easy way to annotate the "value" in my class A to fix this?
Thanks
You have to provide a custom Getter for converting it while de-serializing. I am using google gson for deserializing.
#Entity
#Data
public class A {
#JsonProperty
private String value;
#JsonGetter("value")
public HashMap getValueAsJson(){
return new Gson().fromJson(value, HashMap.class);
}
}

graphql java: global dataFetcher and dynamic object

I'm trying to use GraphQL like client of a REST API. My backend return JSON but in my application client i write graphQL and in client i translate graphQL queries to HTTP call's.
My schema:
type Query {
students: [Student]
}
type Student {
name: String
}
POJO example:
public class Student {
private Integer id;
private String name;
}
My resolver:
public class Query implements GraphQLQueryResolver {
public List<Post> students() {
// HTTP Request
}
}
In all library's implementations i need create a POJO for Student and write a resolver for request in my API.
A way exist to don't need create a POJO and a create global execute resolver?
If you're using libraries like graphql-java-tools (which seems to be the case), you need POJOs, as this is where the library gets its type mappings from. But if you're just using graphql-java itself, you can wire it any way you like - including having a single global resolver (i.e. DataFetcher).
For an idea how to do this, see http://graphql-java.readthedocs.io/en/latest/schema.html#idl
You want something like:
SchemaParser schemaParser = new SchemaParser();
SchemaGenerator schemaGenerator = new SchemaGenerator();
File schemaFile = loadSchema("yourStudentSchema.graphqls");
TypeDefinitionRegistry typeRegistry = schemaParser.parse(schemaFile);
RuntimeWiring wiring = buildRuntimeWiring();
GraphQLSchema graphQLSchema = schemaGenerator.makeExecutableSchema(typeRegistry, wiring);
RuntimeWiring is where you hook the resolvers, e.g:
RuntimeWiring buildRuntimeWiring() {
return RuntimeWiring.newRuntimeWiring()
// this uses builder function lambda syntax
.type("Query", typeWiring -> typeWiring
.dataFetcher("students", env -> fetchDataSomeHow(env)))
.build();
}
So you can provide the same DataFetcher implementation to each dataFetcher call f that's what you're after. graphql-java itself makes no assumptions about way it's wired and implemented, e.g. it does not enforce POJOs or anything else.

Convert entity property camel case to snake case in json in jhipster project

I am working with a project that is generated with jhipster. It is a micro service architecture project.
In my entity class properties are named with camel case. So when I create a rest service it gives me json, where the json property names are as same as the entity properties.
Entity class
#Entity
#Table(name = "ebook")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#Document(indexName = "ebook")
public class Ebook implements Serializable {
private Long id;
private String nameBangla;
private String nameEnglish;
Json response
{
"id": 0,
"nameBangla": "string",
"nameEnglish": "string"
}
I want that my entity property will camel case, But in json response it will snake case. That is I don't want to change my entity class but I want to change my json response like bellow
{
"id": 0,
"name_bangla": "string",
"name_english": "string"
}
You have two possibilities:
Explicit naming your properties:
#JsonProperty("name_bangla")
private String nameBangla;
#JsonProperty("name_english")
private String nameEnglish;
or changing how jackson (which is used for de/serialization) works:
Jackson has a setting called PropertyNamingStrategy.SNAKE_CASE
which you can set for the jackson objectmapper.
So, you need to configure Jackson for that, e.g. by adding your own object mapper:
#Configuration
public class JacksonConfiguration {
#Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
return new Jackson2ObjectMapperBuilder().propertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
}
}
As far as I know, in older version of JHipster, there was already a JacksonConfiguration to configure the JSR310 time module, but was removed later...
Adding this to your application.yml should also work:
spring.jackson.property-naming-strategy=SNAKE_CASE
Also you can use annotation to define naming strategy per class.
Little example in Kotlin:
#JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy::class)
data class Specialization(val altUrl: String, val altId: Int, val altName: String)

Categories