Converting String to java bean type - java

I have a string which looks like this and it represents a pojo.
Model [Name=Mobie , location= US, actualTransferDate=null, scanserialCode=234335,1237787, modelNum=MIC 898989 ]
I want bit clearer to reader on the above string. I want to read the user checked checkbox values(represents entire row with the fileds in below pojo) in an jsp page table to another jsp page. So, in the controller i read these checked checkbox rows as bellow.
String[] checkeditems = request.getParameterValues("case");//case represents the entire row
for (String string : checkeditems) {
log.info("row1"+string);// String pasted above in the message
}
From the above it returns as a string Array which i want convert to be as a list object, so that i can easily send this list to next jsp for a view. I feel i am heading to wrong direction and doing some unrelated stuff.
I have a pojo as
public class Model{
private String Name;
private String location;
private String actualTransferDate;
private String scanserialCode;
private String modelNum;
====Getters/Setter======
How i can convert this String to this model object?

you can split the string on ", " and iterate over the result array. With BeanUtils from apache can you fill your new pojo instance.
Example:
public class Model {
private String Name;
private String location;
private String actualTransferDate;
private String scanserialCode;
private String modelNum;
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getActualTransferDate() {
return actualTransferDate;
}
public void setActualTransferDate(String actualTransferDate) {
this.actualTransferDate = actualTransferDate;
}
public String getScanserialCode() {
return scanserialCode;
}
public void setScanserialCode(String scanserialCode) {
this.scanserialCode = scanserialCode;
}
public String getModelNum() {
return modelNum;
}
public void setModelNum(String modelNum) {
this.modelNum = modelNum;
}
#Override
public String toString() {
return "[Name = " + getName() + "location = " +getLocation() + ", actualTransferDate = " + getActualTransferDate() + ", scanserialCode = " + getScanserialCode() + ", modelNum = " + getModelNum() + "]";
}
}
import org.apache.commons.beanutils.BeanUtils;
public class Main {
public static void main(String[] args) throws IllegalAccessException, InvocationTargetException {
String model = new String("Name=Mobie , location= US, actualTransferDate=null, scanserialCode=234335,1237787, modelNum=MIC 898989");
String[] modelValues = model.split(", ");
Model m = new Model();
for (String value : modelValues) {
String[] s = value.split("=");
String fieldName = s[0];
String fieldValue = s[1];
BeanUtils.setProperty(m, fieldName, fieldValue);
}
System.out.println(m.toString());
}
}
Maven dependency:
<dependencies>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.2</version>
</dependency>
</dependencies>

If you want it completely dynamic, you can use Reflection.
For example, use a regular expression (Pattern/Matcher) to find the [ ... ] part, use the String before that as a class name (assuming you know the package name) and then do a simple comma/equals-sign split in the [ ... ] part and fill the fields via reflection... Not that hard to do.

You can define a constructor in the Model class which accepts the full string as input. The use StringTokenizer with delimiter as ',' to convert the string to a list of tokens. Then tokenizer each token with '='as the delimiter. This way you will have all the members of Model class tokens which can be used to initialize the values of the member variables.

Related

ModelMapper reverse map from a destination field onto itself

Is there a way ModelMapper can reverse map a value already set using PropertyMap again to another field in destination? In other words, I have a computed value and the same has to be set on two fields using PropertyMap, computation changes the value everytime and cannot be invoked twice using(converter).
Introduction
Let's consider the following versions as the current versions:
ModelMapper: 3.1.0.
It seems that by the «ModelMapper» library design:
There is no way to «reuse» the converted source value to set multiple destination property values.
Possible solution
A post-converter may be used to copy a value from one destination property to another.
Draft example program
pom.xml file
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>3.1.0</version>
</dependency>
Customer class
class Customer {
private String fullName;
public String getFullName() {
return fullName;
}
public void setFullName(final String fullName) {
this.fullName = fullName;
}
}
CustomerDTO class
import java.util.StringJoiner;
class CustomerDTO {
private String fullName;
private String copyOfFullName;
public String getFullName() {
return fullName;
}
public void setFullName(final String fullName) {
this.fullName = fullName;
}
public String getCopyOfFullName() {
return copyOfFullName;
}
public void setCopyOfFullName(final String copyOfFullName) {
this.copyOfFullName = copyOfFullName;
}
#Override
public String toString() {
return new StringJoiner(", ", CustomerDTO.class.getSimpleName() + "[", "]")
.add("fullName='" + fullName + "'")
.add("copyOfFullName='" + copyOfFullName + "'")
.toString();
}
}
Program class
import org.modelmapper.Converter;
import org.modelmapper.ModelMapper;
public final class Program {
public static void main(final String[] args) {
final Customer customer = new Customer();
customer.setFullName("Full name");
final ModelMapper modelMapper = new ModelMapper();
final Converter<Customer, CustomerDTO> customerConverter = context -> {
final CustomerDTO destination = context.getDestination();
// NOTE: Copying the value of the full name property to another property.
destination.setCopyOfFullName(destination.getFullName());
return destination;
};
modelMapper.typeMap(
Customer.class, CustomerDTO.class
).addMapping(
Customer::getFullName, CustomerDTO::setFullName
).setPostConverter(customerConverter);
modelMapper.validate();
final CustomerDTO customerDTO = modelMapper.map(customer, CustomerDTO.class);
System.out.println(customerDTO);
}
}
Output
CustomerDTO[fullName='Full name', copyOfFullName='Full name']
Additional references
Post-converter example. java - ModelMapper: transferring attribute from root to each elements of a list - Stack Overflow.
Answer.

Exclude null properties when converting object to string via toString()

class Person {
public String name;
public String nickname;
}
When converting a POJO from Object to String, I want to exclude any values which are null, so that if I have Person = {name = "Jack", nickname = null}, the toString() will just return {name = "Jack"}
Is this use case possible?
Edit: Yes, I am using Lombok. Maybe the solution is to implement my own toString()
References:
https://groups.google.com/forum/#!topic/project-lombok/YC-eo2_XmsI
As for now, this feature of omiting nulls is NYI in lombok, so you will have to implement your own toString method.
You can either use StringJoiner 1 and skip nulls explicitly, or you can use a helper ToStringHelper 2 from Guava
class Person {
public String name;
public String nickname;
#Override
public String toString() {
final var joiner = new StringJoiner(", ", Person.class.getSimpleName() + "[", "]");
if (name != null) {
joiner.add("name='" + name + "'");
}
if (nickname != null) {
joiner.add("nickname='" + nickname + "'");
}
return joiner.toString();
}
#Override
public String toString() {
return MoreObjects.toStringHelper(this)
.omitNullValues()
.add("name", name)
.add("nickname", nickname)
.toString();
}
}
You can use the commons-lang3 to achieve your aim.
The only one thing what you need to do is to override the toString() method in the Person class:
public class Person {
private String name;
private String nickName;
// getters and setters
#Override
public String toString() {
final Object myself = this;
ReflectionToStringBuilder builder = new ReflectionToStringBuilder(this, ToStringStyle.JSON_STYLE) {
#Override
protected boolean accept(Field field) {
try {
return super.accept(field) && field.get(myself) != null;
}
catch (IllegalAccessException e) {
return super.accept(field);
}
}
};
return builder.toString();
}
}
The result if the name field value is not null but nickName is null:
{"name":"John"}
You need to add the following dependency to your pom.xml:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
The benefit of the usage of the ReflectionToStringBuilder class is that you do not need to touch your toString() method if you add a new class member variable because this class uses reflection.

Consider null and empty records as same in Collectors.groupingBy

I have a list of objects where a few records can have empty value property and a few can have null value property. Using Collectors.groupingBy I need both the records to be considered as same.
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class Code {
private String type;
private String description;
public static void main(String[] args) {
List<Code> codeList = new ArrayList<>();
Code c = new Code();
c.setDescription("abc");
c.setType("");
codeList.add(c);
Code c1 = new Code();
c1.setDescription("abc");
c1.setType(null);
codeList.add(c1);
Map<String, List<Code>> codeMap = codeList.stream()
.collect(Collectors.groupingBy(code -> getGroupingKey(code)));
System.out.println(codeMap);
System.out.println(codeMap.size());
}
private static String getGroupingKey(Code code) {
return code.getDescription() +
"~" + code.getType();
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
The result of codeMap will have two records since it considers the empty string and the null value in the Type property as different. How can I achieve getting a single record here by considering both the null and empty records as same.
You can modify your getGroupingKey method like this:
private static String getGroupingKey(Code code) {
return code.getDescription() + "~" + (code.getType() == null ? "" : code.getType());
}
or like this:
private static String getGroupingKey(Code code) {
return code.getDescription() + "~" + Optional.ofNullable(code.getType()).orElse("");
}
or you might as well modify your getType() method directly as in:
public String getType() {
return type == null ? "" : type;
}
or:
public String getType() {
return Optional.ofNullable(type).orElse("");
}
Either should work the same. Pick one depending on your requirements I guess..
If you add the following toString method to your Code class:
#Override
public String toString() {
return "Code{" +
"type='" + type + '\'' +
", description='" + description + '\'' +
'}';
}
.. with the modified getGroupingKey method (or the getType method) the output should be as follows:
{abc~=[Code{type='', description='abc'}, Code{type='null', description='abc'}]}
1
Edit: You can also considering initializing the type to an empty String instead of null, then you would not need to modify anything:
private String type = "";
That might be an option too..

JSON parsing through GSON returns null values

I am trying to read the values of a JSON output.
This is the JSON output:
{"nameOfSummoner":{"id":56529189,"name":"test","profileIconId":550,"summonerLevel":30,"revisionDate":1422110739000}}
And with the following code I am trying to read it:
final Connector connector = new Connector();
String response = connector.connect("link"); // (Returns a String value of the JSON)
final Gson gson = new Gson();
final Summoner summoner = gson.fromJson(response, Summoner.class); //Summoner is a model class
System.out.println(summoner);
Summoner class:
public class Summoner {
private String name;
private long profileIconId;
private long summonerLevel;
private long revisionDate;
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public long getProfileIconId() {
return profileIconId;
}
public void setProfileIconId(final long profileIconId) {
this.profileIconId = profileIconId;
}
public long getSummonerLevel() {
return summonerLevel;
}
public void setSummonerLevel(final long summonerLevel) {
this.summonerLevel = summonerLevel;
}
public long getRevisionDate() {
return revisionDate;
}
public void setRevisionDate
(long revisionDate) {
this.revisionDate = revisionDate;
}
#Override
public String toString() {
return "Summoner{" +
"name='" + name + '\'' +
", profileIconId=" + profileIconId +
", summonerLevel=" + summonerLevel +
", revisionDate=" + revisionDate +
'}';
}
}
And I get the following output on the console:
Summoner{name='null', profileIconId=0, summonerLevel=0, revisionDate=0}
I have sadly no idea why this happens. Any help I get is appreciated. I am fairly sure it has to do with the JSON output that "nameOfSummoner" is on top and maybe that's why it does not read what is below.
As mentioned by #PeterMmm , your input is a map with 1 key-value pair.
You need to Create another POJO with Summoner object as attribute:
public class Sample {
private Summoner nameOfSummoner;
//getters and setters
}
and then try parsing. Or, you could create a Map and parse.
Map<String, Summoner> responseObj = new HashMap<String, Summoner>();
responseObj= gson.fromJson(response, responseObj.class);
Summoner obj = responseObj.get("nameOfSummoner");
You will also need to have "id" attribute in Summoner class I believe, else gson will throw an exception.

Is it possible to remove an attribute (variable) from object in java?

I have a lots of classes that extends from one class
Also I have one method that its argument is that parent class and create query base on attribute of those classes.
sometimes I need to ignore some attribute from result query.
so is it possible to remove some attribute of object?
class A1 extends Model {
public String field1 = "";
public String field2 = "";
public String table = "A1";
#Override
public String getTable() {
return this.table;
}
}
class A2 extends Model {
public String field1 = "";
public String field2 = "";
public String field3 = "";
public String table = "A2";
#Override
public String getTable() {
return this.table;
}
}
class Utility {
public static String query(Model params) {
Field[] fields = params.getClass().getFields();
String head = "INSERT INTO " + params.getTable() + "(";
String tail = "VALUES (";
for(Field field : fields) {
String key = field.getName();
String val;
try {
val = field.get(params);
} catch (Exception e) {
val = null;
}
head += key + ",";
tail += "'" + val + "',";
}
head = head.substring(head,0,head.length() -1) + ")";
tail = tail.substring(tail,0,tail.length() -1) + ")";
return head + tail;
}
}
I call query method by sending one model
A1 data = new A1();
data.field1 = "Name";
data.field2 = "Family";
String query = Utility.query(data);
I just want to remove field2 from query how can I do that?
thanks for any help
You could implement an annotiation. Let's call it #DontPersist. Use it to mark fields which should not get persisted. In Utility.query() you can check for the annotation with reflection.
As your Model class does not implement anything (it could be an interface, but that's another topic), you can extend it creating a class with less attributes when necessary (an anonymous class will do the job).
Anyway, I think you should refactor your code: why not using a List to store fields? It's easier and it does not need reflection.
I'll use something like:
public class Model extends ArrayList{
public Model(String name) { tableName=name;}
private String tableName;
public String getTable() {return tableName}
}
And then you can iterate over the Array to obtain the field names.

Categories