Ignore json POJO fields not mapped in object in spring boot - java

I have pojo which has many fields. I have set value some field. But when i create json, whole pojo create a json . here is the code i have used:
Pojo
public class BasicInfoModel {
private String client_id="";
private String father_name="";
private String mother_name="";
private String gendar="";
//Getter and setter
}
Repository code
public BasicInfoModel getBasicInfo() {
BasicInfoModel lm = new BasicInfoModel();
lm.setFather_name("Enamul Haque");
return lm;
}
Controller code
#RequestMapping(value = "/get_donar_basic_info", method = RequestMethod.POST, produces ="application/json")
public #ResponseBody BasicInfoModel getBasicinfo(){
return repository.getBasicInfo();
}
But my json is resposne like bellow:
{
"client_id": "",
"father_name": "Enamul Haque",
"mother_name": "",
"gendar": ""
}
I have set value to father_name but i have seen that i have found all the value of pojo fields. I want get only set value of father_name and ignor other value which is not set in repository.
My json look like bellow: I will display only father_name.how to display bellow like json from above code?
{
"father_name": "Enamul Haque"
}
Please help me..

Json include non null values to ignore null fields when serializing a java class
#JsonInclude(Include.NON_NULL)
Jackson allows controlling this behavior at either the class level:
#JsonInclude(Include.NON_NULL)
public class BasicInfoModel { ... }
at the field level:
public class BasicInfoModel {
private String client_id="";
#JsonInclude(Include.NON_NULL)
private String father_name="";
private String mother_name="";
private String gendar="";
//Getter and setter
}
from jackson 2.0 use here use
#JsonInclude(JsonInclude.Include.NON_NULL)
You can also ignore the empty values
#JsonInclude(JsonInclude.Include.NON_EMPTY)

Add the #JsonIgnoreProperties("fieldname") annotation to your POJO.
Or you can use #JsonIgnore before the name of the field you want to ignore while deserializing JSON. Example:
#JsonIgnore
#JsonProperty(value = "client_id")
#RequestMapping(value = "/get_donar_basic_info", method = RequestMethod.POST, produces ="application/json")
public #ResponseBody BasicInfoModel getBasicinfo(){
return repository.getBasicInfo();
}

You can ignore field at class level by using #JsonIgnoreProperties annotation and specifying the fields by name:
#JsonIgnoreProperties(value = { "client_id" })
public class BasicInfoModel {
private String client_id="";
private String father_name="";
private String mother_name="";
private String gendar="";
//Getter and setter
}
Or you can use #JsonIgnore annotation directly on the field.
public class BasicInfoModel {
#JsonIgnore
private String client_id="";
private String father_name="";
private String mother_name="";
private String gendar="";
//Getter and setter
}
You can read here more about this.

Related

Why #JsonInclude(JsonInclude.Include.NON_EMPTY) is not working?

I am trying to set null values to database of empty values from JSON payload. This problem caused beacause I have unique constraints on social entity fields.
I have request DTO that looks like:
#Value
#With
#Builder
#Jacksonized
public class AccountCreateRequest {
#NotBlank
String firstName;
String phone;
#Password
#NotBlank
String password;
#Email(message = "Email is not valid.")
#NotBlank
String email;
#NotBlank
String role;
SocialDto social;
}
Nested social DTO looks like
#Value
#Builder
#Jacksonized
public class SocialDto {
#JsonInclude(JsonInclude.Include.NON_EMPTY)
String telegramId;
#JsonInclude(JsonInclude.Include.NON_EMPTY)
String linkedinLink;
#JsonInclude(JsonInclude.Include.NON_EMPTY)
String githubLink;
}
Json example:
{
...fields...,
social: {
telegramId: "",
githubLink: "",
...
}
}
This JSON object is deserialized with social empty strings and doesn't ignore that values.
Moving annotation to the class level - didn't help for me.
How could I fix this problem?
#JsonInclude(JsonInclude.Include.NON_EMPTY) does not work for the intended purpose of treating empty strings as null on object deserialization. This annotation is for including fields in Object to JSON serialization.
You need to add a custom Deserializer like so: How to deserialize a blank JSON string value to null for java.lang.String?
In order to combine this with #Jacksonized, which already registers a #JsonDeserialize(using = x.class) on the class level, you can do the following:
public class JsonStringDeserializer extends JsonDeserializer<String> {
#Override
public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
JsonNode node = jsonParser.readValueAsTree();
String nodeText = node.asText();
// todo: isBlank or isEmpty depending on your needs
if (nodeText.isBlank()) {
return null;
}
return nodeText;
}
}
and parse the JSON object with the following code:
SimpleModule stringModule = new SimpleModule();
stringModule.addDeserializer(String.class, new JsonStringDeserializer());
ObjectMapper jsonObjectMapper = new ObjectMapper();
jsonObjectMapper.registerModule(stringModule);
jsonObjectMapper.readValue(input, modelClass);
Or you can add #JsonDeserialize(using = JsonStringDeserializer.class) on every String field that needs it if you don't control the ObjectMapper.

How to ignore the #JsonProperty value while using the #RequestBody in controller to map value to DTO

I want to MAP my HTTP request parameter value directly to my DTO USING #JsonProperty on the basis of the variable name not by #JsonProperty value. I am not able to map the value to DTO because it's expecting request value according to the JsonProperty name. Is there anyway to disable #JsonProperty value while using the #RequestBody ?
JSON send by frontend:
{
"userId":"1",
"payMethod":"payMethod"
}
MyDto.class
public class MyDto{
#JsonProperty(value = user_id, required = true)
private String userId;
#JsonProperty(value = BETAALMETHODE, required = true)
private String payMethod;
//getter setter
}
MyController.class
public class MyController{
#RequestMapping(value = "payment", method = RequestMethod.PUT)
public Integer PaymentUpdate(#RequestBody final MyDto myDto) throws JsonProcessingException {
}
you can do this by using multiple setter method for that DTO method. For example
Payload:
{
"userId":"1",
"payMethod":"payMethod"
}
then
MyDto.class public class MyDto{
#JsonProperty(value = user_id, required = true)
private String userId;
#JsonProperty(value = BETAALMETHODE, required = true)
private String payMethod;
add one more setter relevant to the required variable name in the DTO class.
#JsonSetter("specifiedName")
void setUserId(String userId){
this.userId=userId
}
void setPayMethod(String payMethod){ // Will work for "BETAALMETHODE" variable name
this.payMethod=payMethod
}
#JsonSetter("payMethod")
void setPayMethod(String payMethod){
this.payMethod=payMethod
}
This will solve your problems and variable payMethod will assign in both the cases.
You can use JacksonMixin during csv parsing:
public abstract class MyDtoMixin {
#JsonProperty(value = user_id, required = true)
private String userId;
#JsonProperty(value = BETAALMETHODE, required = true)
private String payMethod;
}
ObjectMapper mapper = new ObjectMapper(); // or CsvMapper mapper = new CsvMapper();
mapper.addMixInAnnotations(MyDto.class, MyDtoMixin.class);

Trouble reading JSON from URL to java objects / storing in mysql db

I'm a newbie coder having just finished a 6 month coding crash-course. I'm working on a java webapp to demonstrate my skills, and the project idea I had involves retrieving JSON data from an API, something we didn't learn about in class. I made POJOs to match the JSON, and I'm trying to parse the JSON into java objects to store in a database, however my database tables are never filled with data when I run through the app. I suspect the problem is somewhere with my method to convert the JSON but any feedback is greatly appreciated. Here's all my code I think is relevant, sorry if its TMI. I also apologize if my code is ugly, I'm a beginner... Thanks!
API returns JSON like this:
{
"result":{
"status":1,
"num_results":1,
"total_results":500,
"results_remaining":499,
"matches":[{
"match_id":3188095188,
"match_seq_num":2784956606,
"start_time":1495079320,
"lobby_type":7,
"radiant_team_id":0,
"dire_team_id":0,
"players":[{
"account_id":86920222,
"player_slot":0,
"hero_id":18
},{
"account_id":61122568,
"player_slot":1,
"hero_id":85
},{
"account_id":10208661,
"player_slot":2,
"hero_id":13
},{
"account_id":106083675,
"player_slot":132,
"hero_id":50
}]
}]
}
}
My POJOs:
#Entity
#JsonIgnoreProperties(ignoreUnknown = true)
public class Result {
#JsonIgnore
#Id
#GeneratedValue
private int id;
#JsonProperty("status")
private int status;
#JsonProperty("num_results")
private int num_results;
#JsonProperty("total_results")
private int total_results;
#JsonProperty("results_remaining")
private int results_remaining;
#OneToMany
#JoinColumn(name = "result_id")
#ElementCollection(targetClass=Matches.class)
#JsonProperty("matches")
private List<Matches> matches;
// getters and setters
}
#Entity
#JsonIgnoreProperties(ignoreUnknown = true)
public class Matches {
#Id
#JsonProperty("match_id")
private int match_id;
#JsonIgnore
#ManyToOne
private Result result;
#JsonProperty("match_seq_num")
private int match_seq_num;
#JsonProperty("start_time")
private int start_time;
#JsonProperty("lobby_type")
private int lobby_type;
#JsonProperty("radiant_team_id")
private int radiant_team_id;
#JsonProperty("dire_team_id")
private int dire_team_id;
#OneToMany
#JoinColumn(name = "Matches_id")
#ElementCollection(targetClass=Players.class)
#JsonProperty("players")
private List<Players> players;
// getters and setters
}
#Entity
#JsonIgnoreProperties(ignoreUnknown = true)
public class Players {
#JsonIgnore
#Id
#GeneratedValue
private int id;
#JsonIgnore
#ManyToOne
private Matches matches;
#JsonProperty("account_id")
private int account_id;
#JsonProperty("player_slot")
private int player_slot;
#JsonProperty("hero_id")
private int hero_id;
// getters and setters
}
Services method to read and convert the JSON to objects (url is censored, don't want my API key to be public)
public class SteamService {
public static Result getMatchHistory(String steamid){
Result result = new Result();
String MatchHistoryUrl = "https:**URL**="+steamid;
RestTemplate restTemplate = new RestTemplate();
Result jsonresult = restTemplate.getForObject(MatchHistoryUrl, Result.class);
return jsonresult;
}
}
Controller
#Controller
#RequestMapping("")
public class HomeController {
#Autowired
private ResultsDao resultsDao;
#RequestMapping(value = "", method = RequestMethod.GET)
public String index(Model model){
model.addAttribute("title", "Welcome");
return "home/home";
}
#RequestMapping(value = "", method = RequestMethod.POST)
public String processSteamIdField(#RequestParam("steamid")String steamid, Model model) {
Result newresult = getMatchHistory(steamid);
resultsDao.save(newresult);
return "redirect:results";
}
}
DAO
#Repository
#Transactional
public interface ResultsDao extends CrudRepository<Result, Integer>{
}
Maybe my approach is a bit naive, but... If you want to store the JSON as string in the database, then I would use an object mapper for this:
new ObjectMapper().writeValueAsString(myObject);
and for reading a JSON and parsing it to a class I would do:
new ObjectMapper().readValue(JSON_STRING_HERE, "utf-8"), MyPOJO.class);
Also, if you already are using Spring, then your controller may look like this (for a POST, for example)
#RequestMapping(value = "/", method = RequestMethod.POST)
public MyPojo myController(#RequestBody MyPojo myBody) {
myRepository.save(myBody);
}
So, the parsing of the JSON that the client is sending to your app and your controller is already handled by Spring

How to display class as a JSON response in Java?

Currently I'm working on spring project and I want to display class as a JSON response. Following is the class template and other related details.
public class Country {
#Column(name = "name")
private String name;
#Id
#Column(name = "code")
private String Code;
//Getters & Setters ...
}
current response :
[{"name":"Andorra","code":"AD"},{"name":"United Arab Emirates","code":"AE"}]
Expected response :
[ { "countries" : [{"name":"Andorra","code":"AD"},{"name":"United Arab Emirates","code":"AE"}], "status" : "ok", "message":"success", etc..etc...}]
instead of status and message, it could be some array list too.
You need create class contain list and use ResponseEntity.
public class Foo {
private List<Country> countries;
// get/set...
}
#Controller
public class MyController {
#ResponseBody
#RequestMapping(value = "/foo", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
public ResponseEntity<Foo> foo() {
Foo foo = new Foo();
Country country = new Country();
foo.getCountries().add(country);
return ResponseEntity.ok(foo);
}
}
You should create another object, e.g. called Countries as shown below:
public class Countries {
private List<Country> countries;
// getters & setters
}
or:
public class Countries {
private Country[] countries;
// getters & setters
}
The list or array of Country objects will map to your expected {"countries" : [{"name":"Andorra","code":"AD"},{"name":"United Arab Emirates","code":"AE"}]}, because the JSON {} refers to some object and [] refers to list/array in Java code.
Actually you can also achieve using jackson library.
//Create obj of ObjectMapper
ObjectMapper mapper = new ObjectMapper();
//Get the Json string value from the mapper
String json = mapper.writeValueAsString(obj)
And then return this json string in your controller method.
The advantage of using this is that, you can also ignore certain fields in the POJO for JSON conversion using #JsonIgnore annotation (Put this annotation before the getter of the field that you want to ignore) (Not sure if you can do the same from Spring ResponseEntity.
Note: Please correct me if I am wrong anywhere.

Spring class RequestBody and MongoRepository

I have class:
class TestClass {
#Id
private ObjectId id;
private ObjectId parentId;
private String name;
private String describe;
private String privateData;
public TestClass(ObjectId parentId, String name, String describe, String privateData) {
this.parrentId = parrentId;
this.name = name;
this.describe = describe;
this.privateDate = privateData;
}
// get/set methods...
}
Can I use this class in MongoRepository and #RequestBody? Is it safe? parrentId and privateData is private properties and RequestBody does not have to fill them.
mongorepository:
public interface TestClassRepository extends MongoRepository<TestClass, String> {
public TestClass findById(ObjectId id);
}
post method:
#RequestMapping(value="/testclass", method=RequestMethod.POST)
public void create(#RequestBody TestClass testClass) {
testClass.setParentId(...);
repo.insert(testClass);
}
For example:
{"name": "test", "describe": "test", "id": "54d5261a8314fe3c650d5b1d", "parentId": "54d5261a8314fe3c650d5b1d", "privateData": "WrongPrivateData"}
How can I do that it was impossible to set properties id, parentId, privateDate?
Or need I create new class for RequestBody? I don't want duplicate code.
It should be better and safe to use separate models for DAO and VO layers(view). If your models currently looks the same, it doesn't mean that they will stay the same in future. You can use the Dozer Mapping framework for mappings between your models. It's easy,fast and safe.
If you need to skip some field from mongotemplate mapping use #Transient annotation.
P.S. You don't need findById method, because mongotemplate already have find method which uses key as param. TestClass should have an empty constructor.

Categories

Resources