Say I have serialized the following object as json string:
class Person {
public final String name;
public Person(String name) { this.name = name; }
}
Person p = new Person("Bob Falaway");
JsonObject json = gson.toJsonTree(p, Person.class).getAsJsonObject();
Now I want to deserialize it, but I want to split split the name into two fields, firstName and lastName. How do I do this?
I want the end to result in a class similar to:
class RefinedPerson {
public final String firstName;
public final String lastName;
public String toString() { return String.format("%s %s", firstName, lastName); }
}
Is this at all possible with Gson?
Register your own JsonSerializer for the type (or TypeAdapter if you'd prefer)?
Something like:
#JsonAdapter(PersonSerializer.class)
class Person {
private final String name;
Person(final String name) {
// Some validation...
this.name = name;
}
String getName() {
return this.name;
}
}
Where your serialiser looks something like:
class PersonSerializer implements JsonSerializer<Person> {
#Override
public JsonObject serialise(final Person src,
final Type personType,
final JsonSerializationContext context) {
final JsonObject json = new JsonObject();
final String[] names = src.getName().split(" ");
// Some validation...
json.addProperty("firstName", names[0]);
json.addProperty("lastName", names[1]);
return json;
}
}
Related
I have come across a situation where I have to support existing client, they are using below payload for rest api,
{
"firstName": "First name",
"secondName": "Second name",
"dateOfBirth": "01/12/2020",
"profession": "Software Developer",
"salary": 0,
**"value": "value1"**
}
but now as per requirement, they may send array for value field like below :
{
"firstName": "First name",
"secondName": "Second name",
"dateOfBirth": "01/12/2020",
"profession": "Software Developer",
"salary": 0,
**"value": ["Value1", "value2", "Value3"]**
}
Existing code uses #RequestBody to convert it to PersonDTO person, this class also contains a method called isMutliValue() & getMultiValueFor(), and these methods splits the string based on comma then decide and return values out of it. but now for this requirement, I have to made a modification to check if client is sending array in value or simple string. if it is a simple string then don't split it based on comma and simply process it but if it is an array, bring values out of it and send individual values.
public class PersonDTO {
private String firstName;
private String secondName;
// Formats output date when this DTO is passed through JSON
#JsonFormat(pattern = "dd/MM/yyyy")
// Allows dd/MM/yyyy date to be passed into GET request in JSON
#DateTimeFormat(pattern = "dd/MM/yyyy")
private Date dateOfBirth;
private String profession;
private BigDecimal salary;
private String value;
public PersonDTO(
String firstName, String secondName, Date dateOfBirth, String profession, BigDecimal salary, String value) {
this.firstName = firstName;
this.secondName = secondName;
this.dateOfBirth = dateOfBirth;
this.profession = profession;
this.salary = salary;
this.value = value;
}
public PersonDTO() {}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getSecondName() {
return secondName;
}
public void setSecondName(String secondName) {
this.secondName = secondName;
}
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public String getProfession() {
return profession;
}
public void setProfession(String profession) {
this.profession = profession;
}
public BigDecimal getSalary() {
return salary;
}
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public boolean isMultiValued() {
return value.split(",").length > 1;
}
public String[] getMultiValues() {
return value.split(",");
}
public String toString(){
return "FirstName : " + firstName +" SecondName : "+ secondName +", Value : "+ value.toString();
}
}
please help me out, how can we handle different type of values in single field of json payload.
In this case you can implement custom deserialization. so for this purpose you should define a PersonDTODeserializer that extends from JsonDeserializer and override deserialize method.
public class PersonDTODeserializer extends JsonDeserializer {
#Override
public Object deserialize(JsonParser jsonParser,
DeserializationContext deserializationContext) throws IOException {
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
String name = node.get("firstName").textValue();
String secondName = node.get("secondName").textValue();
BigDecimal salary = node.get("salary").decimalValue();
String value = "";
JsonNode nodeValue = node.get("value");
if (nodeValue.isArray()) {
Iterator<JsonNode> nodeIterator = nodeValue.iterator();
List<String> values = new ArrayList<>();
while (nodeIterator.hasNext()) {
values.add( nodeIterator.next().textValue());
}
value = String.join(",",values);
} else if (nodeValue.isTextual()) {
value = nodeValue.textValue();
}
return new PersonDTO(name, secondName, salary, value);
}
}
and use it in PersonDTO class.
#JsonDeserialize(using = PersonDTODeserializer.class)
public class PersonDTO {
//other
}
Based on #Hadi J answer,
you can set the deserializer on this field only and not the whole class :
public class PersonDTO {
// ...
#JsonDeserialize(using = ValueDeserializer.class)
private String value;
// ...
}
and the Deserializer:
private static class ValueDeserializer extends JsonDeserializer<String> {
#Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
if( p.isExpectedStartArrayToken() ) {
List<String> values = new ArrayList<String>( p.readValueAs(List.class) );
return String.join(",", values);
} else {
return p.getValueAsString();
}
}
}
i have problem with my list. My goal is to make a JTree from my json list. To do it i convert my json where i have my patients to list. But i cannot even display the name of mine patient. Maybe my code make my problem clearer. I would be grateful for any suggestion!
My patient class:
public class Patient {
private String name;
private String surname;
private String pesel;
public Patient(String name, String surname, String pesel) {
this.name = name;
this.surname = surname;
this.pesel = pesel;
}
public String getName(){return name;}
public void setName(String name){this.name = name;}
public String getSurname(){return surname;}
public void setSurname(String surname){this.surname = surname;}
public String getPesel(){return pesel;}
public void setPesel(String pesel){this.pesel = pesel;}
}
My patientList:
(This method works, when i am using it to convert medicine json to medicine list i have no problem)
public List<Patient> FromJsonToArray1() throws IOException {
String patientsJson = initArray("Patients.json").toString();
Gson gson = new Gson();
java.lang.reflect.Type patientsListType = new TypeToken<ArrayList<Patient>>() {}.getType();
List<Patient> patientArray = gson.fromJson(patientsJson, patientsListType);
return patientArray;
}
And this is my function to show name of mine patient.
public void jtreecreator() throws IOException {
List<Medicine> medicineList = FromJsonToArray();
List<Patient> patientList = FromJsonToArray1();
medicinesDataMethods medicinesdatamethods = new medicinesDataMethods();
DefaultMutableTreeNode root = new DefaultMutableTreeNode("Patients");
Patient c = patientList.get(0);
Medicine d = medicineList.get(0);
DefaultTreeModel treeModel = new DefaultTreeModel(root);
JTree tree = new JTree(treeModel);
JScrollPane scrollPane = new JScrollPane(tree);
JOptionPane.showMessageDialog(null,c.getSurname());
JOptionPane.showMessageDialog(null, d.getName());
}
And after call this function it display d.getName(), but c.getSurname() didnt work.
Its my json where i store my patients:
[
{
"Pesel": "1111",
"Surname": "Walker",
"Name": "Johny "
},
{
"Pesel": "11111",
"Surname": "Walker1",
"Name": "Johny1 "
}
]
After debug, i find out that my list which is created in FromJsonToArray1() has objects of patients but values of name, surname and pesel are null. :C
Issue is attribute names in class and json do not match. You can modify Patient class like
class Patient {
#SerializedName("Name")
private String name;
#SerializedName("Surname")
private String surname;
#SerializedName("Pesel")
private String pesel;
// getters and setters, constructor, etc. here
}
I am trying to retrieve the data from database and return them in 'Response' as JSON array.
But now I am getting the result in browser as below, which is not the correct JSON array format. How can I receive the data as JSON Array ?
{"{\n \"id\": 14,\n \"name\": \"Test Doom Post\",\n \"email\": \"test#test1.com\...
JDK 1.7
Jersey (jaxrs-ri-2.25.1)
Gson
//Following is my Get method below:
#Path("/register")
public class JSONService {
#GET
#Path("/get")
#Produces("application/json")
#Consumes("application/json")
public Response getRegisterInJSON() {
JSONObject requestedJSON = new JSONObject();
try {
Class.forName("com.mysql.jdbc.Driver");
SoccerUtils dbConnection = new SoccerUtils();
Connection conn = dbConnection.getWeekendDBConnection();
PreparedStatement stmt = conn.prepareStatement("SELECT ID, FIRST_NAME, EMAIL FROM mycoolmap.weekendsoccer_login");
ResultSet rs = stmt.executeQuery();
while(rs.next())
{
RegisterPlayer playerObj = new RegisterPlayer();
playerObj.setId(rs.getInt("ID"));
playerObj.setName(rs.getString("FIRST_NAME"));
playerObj.setEmail(rs.getString("EMAIL"));
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json1 = gson.toJson(playerObj);
requestedJSON.put(json1, json1);
System.out.println(requestedJSON);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
}
return Response.status(Status.OK).entity(requestedJSON.toString()).build();
}
// Register Player POJO class:
#XmlRootElement
public class RegisterPlayer implements Serializable {
private int id;
private String name;
private String email;
public RegisterPlayer() {
}
public RegisterPlayer(int id, String name, String email)
{
super();
this.id =id;
this.name = name;
this.email = email;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id =id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getEmail()
{
return email;
}
public void setEmail(String email)
{
this.email = email;
}
#Override
public String toString() {
return "RegisterPlayer[id=" + id +", name=" + name +", email="+ email +"]";
}
}
As advised by Roman in above comment, I have created a list, add the object and return the list. It worked as expected.
/Created a 'registerPlayerList' List
List<RegisterPlayer> registerPlayerList = new ArrayList<RegisterPlayer>();
// Intialiaze the RegisterPlayer class
RegisterPlayer playerObj = new RegisterPlayer();
//set all the values into the object
playerObj.setId(rs.getInt("ID"));
playerObj.setName(rs.getString("FIRST_NAME"));
playerObj.setEmail(rs.getString("EMAIL"));
......
//add the playerObj to the created registerPlayerList
registerPlayerList.add(playerObj);
// return the list
return registerPlayerList ;
The problem is that you're printing the json to string (the json1 variable), but you're adding that string to a JSONObject. When a string is added to a JSONObject, the string will be escaped - that's a String json object.
If you print json1 instead (and set that as the entity), it should work.
I am trying to convert json format (arraylist response from rest webservice) to corresponding java arraylist.
Surpisingly, only 2 of 3 variables are getting formatted into object and 3 variable is setting into null.
Below is the json response in string format.
[{"points":"20","shares":"54","name":"Krishna"},{"points":"18","shares":"47","name":"Bhima"}]
I am trying to convert to arraylist with below code:
ArrayList<GplusFriend> gp_list;
Gson gson = new Gson();
gp_list = gson.fromJson(result, new TypeToken<List<GplusFriend>>(){}.getType());
Iterator itr = gp_list.iterator();
GplusFriend gf =null;
while(itr.hasNext()){
gf= (GplusFriend) itr.next();
Log.d("Restcall", "Name :"+gf.getName());
Log.d("Restcall", "points :"+gf.getPoints());
Log.d("Restcall", "shares :"+gf.getShares());
}
But I am getting the log as :
Name :null
points :20
shares :54
Name :null
points :18
shares :47
This is the class definition of GPlusFriend:
public class GplusFriend {
String Name;
String points;
String shares;
public String getShares() {
return shares;
}
public void setShares(String shares) {
this.shares = shares;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getPoints() {
return points;
}
public void setPoints(String points) {
this.points = points;
}
public GplusFriend(){
super();
}
public GplusFriend(String Name,String points,String shares){
super();
this.shares=shares;
this.Name = Name;
this.points = points;
}
#Override
public String toString(){
return this.Name + " "+this.points+" "+this.shares;
}
}
So what I am missing here..
should be
String name;
instead of
String Name;
your JSON key is in small letter "name"
when using GSON, Variable names are case-sensitive
How to assign value to this function in Java incompatible types?
public class CustomerInfo implements Serializable {
private static final long serialVersionUID = 9083257536541L;
protected String id;
protected String searchkey;
protected String taxid;
protected String name;
protected String postal;
/** Creates a new instance of UserInfoBasic */
public CustomerInfo(String id) {
this.id = id;
this.searchkey = null;
this.taxid = null;
this.name = null;
this.postal = null;
}
public String getId() {
return id;
}
public String getTaxid() {
return taxid;
}
public void setTaxid(String taxid) {
this.taxid = taxid;
}
public String getSearchkey() {
return searchkey;
}
public void setSearchkey(String searchkey) {
this.searchkey = searchkey;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPostal() {
return postal;
}
public void setPostal(String postal) {
this.postal = postal;
}
public String printTaxid() {
return StringUtils.encodeXML(taxid);
}
public String printName() {
return StringUtils.encodeXML(name);
}
#Override
public String toString() {
return getName();
}
}
private CustomerInfo selectedCustomer;
public CustomerInfo getSelectedCustomer() {
// construct a CustomerInfo from the data in your String
return selectedCustomer;
}
private void jcmdOKActionPerformed(java.awt.event.ActionEvent evt) {
selectedCustomer = (CustomerInfo) jListCustomers.getSelectedValue();
//test code
String testing = m_jtxtName.getText();
System.out.println("Now the selectedCustomer is dispayed!");
System.out.println(selectedCustomer);
System.out.println(testing);
//test code
dispose();
}
In the above shown code, I need the string testing value to be assigned to selectedCustomer. How can I assign the value? This is the error I get:
selectedCustomer = m_jtxtName.getText();
incompatible types
required: CustomerInfo
found: String
You can't!!!
selectedCustomer is an object of type CustomerInfo.
m_jtxtName.getText() returns a String
You can't assign a String to a CustomerInfo.
Probably you need to do something like:
int id = 1; //Or whatever new id you have.
String name = m_jtxtName.getText();
selectedCustomer = new CustomerInfo(name); //or whatever id you have.
selectedCustomer.setName(name); //or whatever name you have.
EDIT:
Something is missing from your class. Either it needs setter methods (it has only getters now, so you can't set other properties as name etc) or it needs a constructor with four arguments like:
public CustomerInfo(String id, String searchKey, String taxid, String name, String postal) {
this.id = id;
this.searchKey = searchKey;
// etc
In this case, you might have six jtextfields in your screen, so te user can fill all fields and the create the Customerinfo object by passing all parameters to the constructor.
you cannot do it by simply casting a String to a CustomerInfo object, but you could extend your CustomerInfo but you could try something like this:
public class CustomerInfo {
[...]
public static CustomerInfo createCustomerInfo(String data) {
// construct a CustomerInfo from the data in your String
return createdCustomerInfo;
}
}
I don't know what data you have in that String so i can not give you an advice how to implement this. e.g. If it is the ID you could use this to retrieve the CustomerInfo from database or something like that.