I have following class
public class Employee {
#JsonPropery("name")
private String name;
#JsonPropery("address")
private Address address;
// getter setters
}
And
public class Address {
#JsonPropery("street")
private String name;
#JsonPropery("location")
private String name;
// getter setters
}
Now while generating the JSON for this model, following error is obtained:
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:251)
at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:183)
Can you Please help out in what should be used in place of #JsonProperty here.
If the referenced class is removed , Proper JSON is obtained. Is there any specific annotation to be used for class reference ?
Related
I am following this article https://quarkus.io/guides/rest-client to build a REST Client to parse the output from the restcountries.eu service.
Here the class holding the model:
public class Country {
public String name;
public String alpha2Code;
public String capital;
public List<Currency> currencies;
public static class Currency {
public String code;
public String name;
public String symbol;
}
}
Now, suppose I would like to add a custom fields such as timestamp, to record the instant when this object has been created. I imagine, I would go ahead and add another field like below:
public class Country {
public String name;
public String alpha2Code;
public String capital;
public List<Currency> currencies;
public Instant timestamp; //<--------- added attribute
[....]
My question is: how do I tell the client to populate that field? Normally, I would have done it in the constructor. However, I could not find docs that explain this part.
Thanks for your help
Simone
You can actually do this in the default constructor. Frameworks like JSONB or Jackson expect POJOs to have a default constructor. They will call it when they create an instance of Country.
Use the #JsonbTransient or #JsonIgnore annotations to mark that attribute of your POJO as ignorable in order to avoid the unmarshaller complaining about attributes that cannot be found in the response.
#Data
public class Country {
private String name;
private String alpha2Code;
private String capital;
private List<Currency> currencies;
#JsonbTransient // if you're using JSONB (default in Quarkus)
#JsonIgnore // if you're using Jackson
private Instant timestamp;
public Country() {
this.timestamp = Instant.now();
}
PS The #Data annotation is something you should consider using. Encapsulation is not a bad thing but creating getters/setters is tedious. But Project Lombok certainly helps here.
Need some help here! I have a Java Rest API which is getting data from a .net endpoint and passing it on to the UI. The JSON properties are in capital case and I want to convert them in JAVA before sending it to the UI. Any pointers on this?
In java, I have a class like below:
public class Person {
#JsonProperty("Name")
private String name;
#JsonProperty("Age")
private int age;
}
I am using #JsonProperty as keys in .net are starting with capitalCase. How can I convert this back before sending it to the UI in Java?
Thanks for the help!
Create another class with the same structure and use there other names that you want. Something like this:
// Class to read .NET object
public class Person {
#JsonProperty("Name")
private String name;
#JsonProperty("Age")
private int age;
}
// Class to represent the object in Java REST API
public class Person {
#JsonProperty("name")
private String name;
#JsonProperty("age")
private int age;
}
// Class to represent the object in Java REST API,
// in case you use some standard library that
// uses property names for JSON as is
public class Person {
private String name;
private int age;
}
Of course you should put these classes into different packages.
Your code can look as follows:
xxx.dotnet.Person dotnetPerson = doSomethingViaDotNet(...);
yyy.rest.Person restPerson = new yyy.rest.Person();
restPerson.setName(dotnetPerson.getName());
restPerson.setAge(dotnetPerson.getAge());
...
return restPerson;
If you decide to use MapStruct, your code may looks as follows:
#Mapper
public interface PersonMapper {
PersonMapper INSTANCE = Mappers.getMapper( PersonMapper.class );
yyy.rest.Person dotnetToRest(xxx.dotnet.Person dotnetPerson);
}
Since all attributes have the same names and types you don't need anything else in your mapper.
MapStruct will generate a class that implements this interface. Usage will be as follows:
restPerson = PersonMapper.INSTANCE.dotnetToRest(dotnetPerson);
I have a JSON response like below image, and I have made a serializable class named as Project
In the image, I have two objects (emergency_contact, and secondary_owner) inside my an array of one object. I'm trying to figure out whether what to do in order to define the object, since I want that details to be present inside my constructor.
I have done this so far:
public class Project implements Serializable {
public int id;
public String name;
public String additional_information;
//Now what to do Emergency contact
public Project(int id, String name, String additional_information){
}
}
I have thought of doing this, public EmergencyContact emergency = new EmergencyContact(param1, param2).
And make a new class named as EmergencyContact, and do a getter and setter for the params. But after doing this, I'm still confused, how would I define it my constructor?
I know I'm close, but I need some help on that.
Sure. You need to have a:
public class EmergencyContact implements Serializable {
public String name;
public String number;
public EmergencyContact(String name, String number){
// assign fields
}
}
and one for the owner:
public class EmergencyOwner implements Serializable {
public String name;
public String number;
public EmergencyOwner(String name, String number){
// assign the fields
}
}
then in your Project class you can add fields of these classes:
public class Project implements Serializable {
public int id;
public String name;
public String additional_information;
public EmergencyContact emergency_contact;
public EmergencyOwner emergency_owner;
public Project(int id, String name, String additional_information, EmergencyContact emergency_contact, EmergencyOwner emergency_owner){
// assign the fields here as well
}
}
that's it. If that's an answer to the question consider to delete this question as it is a duplicated on a 100% :)
As a note, to be correctly from the point of clean code parameters, the fields should be private in a class, and use setters / getters to set/retrieve values from/to those fields.
public class Project implements Serializable {
private int id;
private String name;
private String additional_information;
private EmergencyContact emergency_contact;
private SecondaryOwner secondary_owner;
public Project(int id, String name, String additional_information, EmergencyContact emergencyContact, SecondaryOwner secondaryOwner){
this.id = id;
this.name = name;
this.additional_information = additional_information;
this.emergency_contact = emergencyContact;
this.secondary_owner = secondaryOwner;
}
}
You will define the other two classes the same way. Now, you are probably confused about the constructor of EmergencyContact & SecondaryOwner classes.. You can device both default constructors (without parameters) and a custom one(with parameters to it, just as the one above). If you use the default constructor, make sure to set values to the fields in the object, as following :
EmergencyContact emergencyContact = new EmergencyContact();
emergencyContact.setName("the name");
emergencyContact.setNumber("a number");
then you can use this object in the constructor of Project class
I hope it was clear enough, for any other clarifications feel free to ask.
Happy coding <3
I have a model like this:
public class Employee {
#JsonProperty("emplyee_id")
private Integer id;
#JsonProperty("emplyee_first_name")
private String firstName;
#JsonProperty("emplyee_last_name")
private String lastName;
#JsonProperty("emplyee_address")
private String address;
#JsonProperty("emplyee_age")
private Byte age;
#JsonProperty("emplyee_level")
private Byte level;
//getters and setters
}
now I need to create two JSONs using this (only) model.
the first one must like this for example:
{
"employee_id":101,
"employee_first_name":"Alex",
"employee_last_name":"Light",
"employee_age":null,
"employee_address":null
}
and the second one must like this for example:
{
"employee_id":101,
"employee_level":5
}
by the way, I already tested #JsonIgnore and #JsonInclude(JsonInclude.Include.NON_NULL).
the problem of the first one (as much as I know) is, those fields can't be included in other JSONs (for example if level get this annotation, it won't be included in the second JSON)
and the problem of the second one is, null values can't be included in JSON.
so can I keep null values and prevent some other property to be included in JSON without creating extra models? if the answer is yes, so how can I do it? if it's not I really appreciate if anyone gives me the best solution for this state.
thanks very much.
it could be useful for you using #JsonView annotation
public class Views {
public static class Public {
}
public static class Base {
}
}
public class Employee {
#JsonProperty("emplyee_id")
#JsonView({View.Public.class,View.Base.class})
private Integer id;
#JsonProperty("emplyee_first_name")
#JsonView(View.Public.class)
private String firstName;
#JsonProperty("emplyee_last_name")
#JsonView(View.Public.class)
private String lastName;
#JsonProperty("emplyee_address")
private String address;
#JsonProperty("emplyee_age")
private Byte age;
#JsonProperty("emplyee_level")
#JsonView(View.Base.class)
private Byte level;
//getters and setters
}
in your json response add #JsonView(Public/Base.class) it will return based on jsonview annotations
//requestmapping
#JsonView(View.Public.class)
public ResponseEntity<Employee> getEmployeeWithPublicView(){
//do something
}
response:
{
"employee_id":101,
"employee_first_name":"Alex",
"employee_last_name":"Light",
"employee_age":null,
"employee_address":null
}
for the second one
//requestmapping
#JsonView(View.Base.class)
public ResponseEntity<Employee> getEmployeeWithBaseView(){
//do something
}
response
{
"employee_id":101,
"employee_level":5
}
I have a base Summary class below:
public Class Summary{
private String name;
private String status;
private String id;
// Getters and setters
}
I then extended this class to get Customer summary:
public Class CustomerSummary extends Summary{
private String lastLogin;
private String address;
// Getters and setters
}
Now I am calling a Rest endpoint that maps the response to Summary object. I then need to set the lastLogin and address calling another rest endpoint and return the combined data as CustomerSummary object.
Summary summary = restClient.getStatus("1234");
CustomerSummary customer = new CustomerSummary()
How do I set all the inherited fields of customer object same a as the summary object? I can't cast since I will have to down cast and will run into ClassCastException.
I may have 10s of fields so calling setters of customer object for all the fileds of summary object will result in a lot of duplicate code. Is there a smarter way to handle this?
You could make a "copy-constructor"
protected Summary(Summary template){
this.name = template.name;
// ....
}
and call that from your subclasses
CustomerSummary(Summary template){
super(template);
}
so that you can do
Summary summary = restClient.getStatus("1234");
CustomerSummary customer = new CustomerSummary(summary);