JAX-RS serialize only few properties - java

We have a DTO like below
public class Student {
private String name;
private String id;
private ExamResults results;
private Address residentialAddress;
private Address permanentAddress;
// setter and getter methods
}
The same DTO is used by multiple endpoints like student/details/{studId}, student/details/{studId}/results
In student/details/{studId} endpoint we dont populate results property. But still it is being returned as null in the response.
Similarly, in student/details/{studId}/results we dont populate permanentAddress and residentialAddress, but still these are being returned as null in the response.
Basically, I would like to control what properties are serialized based on the endpoint irrespective of whether they are null or not.
Thanks.

You can try to use
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Student {

Related

Http Response parameter name incorrect using Spring Boot/Angular

I'm trying to display a table listing the Country codes (iso3166) in a postgresql db onto an html page using Spring Boot and Angular, the parameter name in the http response lists "number" when instead I want it to list "nbr".
The SQL table has 4 columns
name (varchar) unique
alpha2 (varchar) PK unique
alpha3 (varchar) unique
nbr (int4)
My Spring Boot Models is the following:
#Entity
#Table(name = "iso3166")
public class Country {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private String alpha2;
#Column(name = "name")
private String name;
#Column(name = "alpha3")
private String alpha3;
#Column(name = "nbr")
private int nbr;
public Country()
{
}
public Country(String name, String alpha2, String alpha3, int nbr)
{
this.name = name;
this.alpha2 = alpha2;
this.alpha3 = alpha3;
this.nbr = nbr;
}
/*
getters and settings + toString()
*/
The repository uses JPARepository
public interface ICountryRepository extends JpaRepository<Country, String> {
}
And the Controller has only the findAll() method
#RestController
#RequestMapping({"/api"})
public class CountryController {
#Autowired
ICountryRepository countryRepository;
#GetMapping
public List<Country> findAll(){
List<Country> country = countryRepository.findAll();
return country;
}
}
Running spring-boot and opening localhost in chrome, the table shows up just fine.
However, looking at the Response tab under Network, it shows up like this
Shows the same thing if I go to http://localhost:8080/api
[{"alpha2":"AX","name":"AALAND ISLANDS","alpha3":"ALA","number":248},{"alpha2":"AF","name":"AFGHANISTAN","alpha3":"AFG","number":4},{"alpha2":"AL","name":"ALBANIA","alpha3":"ALB","number":8},{"alpha2":"DZ","name":"ALGERIA","alpha3":"DZA","number":12},{"alpha2":"AS","name":"AMERICAN SAMOA","alpha3":"ASM","number":16},{"alpha2":"AD","name":"ANDORRA","alpha3":"AND","number":20},{"alpha2":"AO","name":"ANGOLA","alpha3":"AGO","number":24},
Why does the Http Response return the "nbr" field as "number" instead? And how can I change it to show up as "nbr" in the Http response? Does something happen in the background in Spring Boot when formulating the http response that I can't control?
It is a number because you defined it as a number here, in Country entity:
#Column(name = "nbr")
private int nbr;
The best solution is to create another object which is used for HTTP communication. For example: CountryDTO.
In CountryDTO you can define nbr field as String.
Then you just have to create a mapping between Country and CountryDTO objects.
Why you should always do like this:
You should never send Entities directly to the client.
It keeps your code clean and separated: One object is responsible for holding the database model, and another is responsible for communicating with the client. It is now the same, and it is just pure luck.
Found out what happened, although I don't know the specifics.
spring uses Jackson to serialize, and Jackson uses by default public getters to serialize and name data.
Since I named the nbr getter/setters as getNumber() and setNumber, changing it to getNbr() and setNbr() respectively solved the issue.

MongoDB map Java POJO without org.bson.types.ObjectId

I want to map Java POJO to MongoDB and implement CRUD operations. I follow manual https://mongodb.github.io/mongo-java-driver/3.11/driver/getting-started/quick-start-pojo/ and all seems fine but one Person property is MongoDB dependent:
public final class Person {
private ObjectId id;
private String name;
private int age;
private Address address;}
This is org.bson.types.ObjectId id. This makes my domain layer dependent on MongoDB, and this actually what I would not call a POJO at all. Instead of ObjectId I would like to have String or other Java core class like Long or something like that. It could could be a kind of getter/setter too. How can I achieve this?
I tried to remove id from Person
package com.mongo_demo.domain;
public final class Person {
private String name;
private int age;
private Address address;}
and use this as my domain object, while to operate with MongoDB in DAO I will use child class:
package com.mongo_demo.mongo_domain;
public final class Person extends com.mongo_demo.domain.Person {
private ObjectId id;
}
Obviously my domain class now not have dependencies on MongoDB, but still lacks String id and no way to have getter method for it, as ObjectId id attribute is in child class.
I not sure is it fine to not have access to id value in my services code, because I could need to call delete by id operation, otherwise I will have to create my own object unique identifier, in addition to ObjectId id attribute, which will be natural key with consequent drawbacks.
PS No getter-setter methods shown, as I use Lombok #Data annotations instead.

Filter field received from rest service using RestTemplate

I am using spring RestTemplate to get data from rest service. The service return list of User object
public Class User{
private String userId;
private String firstName;
private String lastName
//other fields
//getter setter
}
As a client i am only interested on userId field and i don't need other fields.
How can i filter all other properties and only get list of userId.
Note:
Rest service doesn't have filter provision.
I don't want to create a class with only userId as parameter and use annotation #JsonIgnoreProperties(ignoreUnknown = true) and map response to this class
Is there a way to do this.
Read about JsonNode. Then try to retrieve particular key (userId) for every User object. Otherwise you could try make custom Jackson deserializer.

Is it possible to use a MongoRepository with not-fixed document structure? [duplicate]

Mongodb is a no-schema document database, but in spring data, it's necessary to define entity class and repository class, like following:
Entity class:
#Document(collection = "users")
public class User implements UserDetails {
#Id private String userId;
#NotNull #Indexed(unique = true) private String username;
#NotNull private String password;
#NotNull private String name;
#NotNull private String email;
}
Repository class:
public interface UserRepository extends MongoRepository<User, String> {
User findByUsername(String username);
}
Is there anyway to use map not class in spring data mongodb so that the server can accept any dynamic JSON data then store it in BSON without any pre-class define?
First, a few insightful links about schemaless data:
what does “schemaless” even mean anyway?
“schemaless” doesn't mean “schemafree”
Second... one may wonder if Spring, or Java, is the right solution for your problem - why not a more dynamic tool, such a Ruby, Python or the Mongoshell?
That being said, let's focus on the technical issue.
If your goal is only to store random data, you could basically just define your own controller and use the MongoDB Java Driver directly.
If you really insist on having no predefined schema for your domain object class, use this:
#Document(collection = "users")
public class User implements UserDetails {
#Id
private String id;
private Map<String, Object> schemalessData;
// getters/setters omitted
}
Basically it gives you a container in which you can put whatever you want, but watch out for serialization/deserialization issues (this may become tricky if you had ObjectIds and DBRefs in your nested document). Also, updating data may become nasty if your data hierarchy becomes too complex.
Still, at some point, you'll realize your data indeed has a schema that can be pinpointed and put into well-defined POJOs.
Update
A late update since people still happen to read this post in 2020: the Jackson annotations JsonAnyGetter and JsonAnySetter let you hide the root of the schemaless-data container so your unknown fields can be sent as top-level fields in your payload. They will still be stored nested in your MongoDB document, but will appear as top-level fields when the ressource is requested through Spring.
#Document(collection = "users")
public class User implements UserDetails {
#Id
private String id;
// add all other expected fields (getters/setters omitted)
private String foo;
private String bar;
// a container for all unexpected fields
private Map<String, Object> schemalessData;
#JsonAnySetter
public void add(String key, Object value) {
if (null == schemalessData) {
schemalessData = new HashMap<>();
}
schemalessData.put(key, value);
}
#JsonAnyGetter
public Map<String, Object> get() {
return schemalessData;
}
// getters/setters omitted
}

Ignore Java Object's Selected fields while Sending it as JSON

I am new to Spring-MVC.
I am sending data to my view as JSON, and there I am deserializing it to a string, but I want to pass only selected fields, I don't want all fields to send there but how to ignore selected fields I don't know.
My class POJO code :
public class account{
private Integer userId;
private String userName;
private String emailId;
//getter - setter
}
In some activity I don't want some fields so I want to avoid that fields so any idea on this confusing situation ?
Add the annotation #JsonIgnoreProperties("fieldname") to your POJO.
or you can use #JsonIgnore also before field name that you want to ignore while deserializing JSON.
example :
#JsonIgnore
#JsonProperty(value = "user_password")
public java.lang.String getUserPassword()
{
return userPassword;
}
Here Is my Answer for Similar Question.

Categories