I am struggling with unmarshalling an old xml file whose structure is different than my current object structure.
Previous structure
#xmlRootElement("configData")
public class configData{
private string name;
private string age;
private customObject obj;
}
My current data structure is
#xmlRootElement("configData")
public class configData{
List<SampleData> sampleDatas;;
}
public class SampleData{
private string name;
private string age;
private customObject obj;
}
How to make it work with old xml file. Please help.
Thanks
Your old structure suggest, that only one set of SampleData exists in the XML file.
So You should try something like this:
#XmlRootElement
public class ConfigData
{
// This will hide the list from JAXB
#XmlTransient
private final List<SampleData> sampleDatas = new ArrayList<>();
private SampleData getFirstSample()
{
if(sampleDatas.isEmpty())
sampleDatas.add(new SampleData());
return sampleDatas.get(0);
}
// Façade methods to delegate functionality to the list's first item...
// Only setters are required, if you just want to read in an old format.
// However this would not be optional, if you want to save to the new format...
public void setName(String name)
{
getFirstSample().setName(name);
}
public void seAge(String age)
{
getFirstSample().setAge(age);
}
public void setObj(CustomObject obj)
{
getFirstSample().setObj(obj);
}
}
public class SampleData
{
private String name;
private String age;
private CustomObject obj;
// Accessor methods...
}
The façade setter methods in ConfigData store thier values to the List's first item.
To provide the possibility to save, you should remove the #XmlTransient, and provide public getters to the fields you want to save...
Related
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
Let say, I have a student, employee and car class in a different structure in JSON file.
I already parse them and put the respective data to its POJO classes. The things is I wanna display data to inside a recycler view.
But here I have common field both three class is name and weight.
So, I wanna pass to list of generic to recycler view and populate them by calling like this:
tvName.setText(Object(should be generic).getName());
tvWeight.setText(Object(should be generic).getWeight());
It should display name and weight all the student, employee and car .
RecyclerView looks like
---------------------------------------------------------
CarName
CarWeight
---------------------------------------------------------
EmplyoeeName
EmplyoeeWeight
---------------------------------------------------------
StudentName
StudentWeight
---------------------------------------------------------
EmplyoeeName
EmplyoeeWeight
---------------------------------------------------------
CarName
CarWeight
---------------------------------------------------------
CarName
CarWeight
---------------------------------------------------------
StudentName
StudentWeight
Any idea would be highly appreciated.
In order to achieve that, you need something called polymorphism, learn more from StackOverflow, Java Docs and Wikipedia. In order to respect that pattern I would implement the problem like this:
I would create an Interface that has the methods you need:
public interface AttributesInterface {
String getName();
double getWeight();
}
Then I would make every POJO class implement that interface, looking in the end like this:
public class Car implements AttributesInterface {
private String name;
private double weight;
#Override
public String getName() {
return null;
}
#Override
public double getWeight() {
return weight;
}
}
In the adapter you store the list like this. If a class will implement the interface, then you will be able to add it in that array. So you will have an array that will contain Student, Car, Employee in the same time.
private List<AttributesInterface> list = new ArrayList<>();
Then final step is in onBindViewHolder where you get an object from that array and set the corresponding values.
AttributesInterface object = list.get(position);
tvName.setText(object.getName());
tvWeight.setText(String.valueOf(object.getWeight()));
Also, you mentioned that you want a solution to work with multiple classes. As long as you implement the interface in each class that needs to be displayed, you can have a million classes.
You can create only one POJO class and you can add extra variable say type. So your POJO class will look like below.
public class MyClassModel {
private String type=""; // S=Student, C=Car, E=Employee
private String name="", weight="";
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWeight() {
return weight;
}
public void setWeight(String weight) {
this.weight = weight;
}
}
Now you will get type in your RecyclerviewAdapter so you can write your logic according to type of data.
I have a class Person in gwt and I have sent an instance of Person with servlet converted using Gson from server to client. But in the client side seems I can't use Gson. From what I read in forums it seems that the best way is using AutoBeans to convert Json to object Person again.
However in AutoBeans I can only use an interface. I will appreciate if anyone can help me write it.
A json example I get from server and want to convert to Person class again:
{"name":"aaa","family":"fff","username":"uuu","age":20,"phones":[{"id":0,"phoneNumber":"0911111"}],"relatives":[null]}
public class Person implements Serializable {
private String name;
private String family;
private String username;
private int age;
private List<Phone> phones;
private List<Person> relatives;
public Person() {
}
public Person(String name, String family, String username, int age, List<Phone> phones, List<Person> relatives) {
this.name = name;
this.family = family;
this.username = username;
this.age = age;
this.phones = phones;
this.relatives = new ArrayList<Person>();
this.relatives = relatives;
}
public void addPhone(Phone p) {
phones.add(p);
}
public String getName() {
return this.name;
}
public String getFamily() {
return this.family;
}
public int getAge() {
return this.age;
}
public String getUsername() {
return this.username;
}
public List<Phone> getNumbers() {
return this.phones;
}
public List<Person> getRelatives() {
return this.relatives;
}
public String getAllNumbers() {
return Phone.convertPhonesToText(phones);
}
public static Person findPerson(List<Person> personList, String username) {
// .....
}
public static List<Person> convertTextToPersons(List<Person> personList, String personsText) {
// .....
}
public String convertPersonsToText() {
// ....
}
}
Yep, as commented by Tobika the other answer indicates that AutoBeans requires an Interface. AutoBeans feets better if you use it on both sides, client and server side and you define all your models as interfaces.
If you want to use your class models, you can use GWT Jackson which is pretty similar to AutoBeans but it uses your models, binding the json to your model (like other server side libraries; jackson, gson, etc):
https://github.com/nmorel/gwt-jackson
public static interface PersonMapper extends ObjectMapper<Person> {}
#Override public void onModuleLoad() {
PersonMapper mapper = GWT.create(PersonMapper.class);
String json = mapper.write(new Person("John", "Doe"));
GWT.log( json ); // > {"firstName":"John","lastName":"Doe"}
Person person = mapper.read(json);
GWT.log(person.getFirstName() + " " + person.getLastName());
}
Alternatively, you can use just plain GWT with JsInterop. This has many limitations but even with this limitation, it is a pretty good option. This is my favorite option if you can avoid inheritance in your DTOs. But this has the big advantage of being super lightweight (actually zero overhead mapping overhead and zero code overhead as it uses native parsing and no copies, accesing directly to the parsed json object). Limitations: cannot use inheritance, "broken type system" (all X instanceof SomeDtoType returns always true as all DTOs are of type Object wich makes sense because we are actually using the parsed JSON), cannot use collections only native arrays (but thanks to java8 Stream this should not be a problem, whatever you want to do with start with Stream.of(arr)), and only Double and Boolean boxed types supported (not supported any fancy type like Date or BigInteger, not supported long/Long...).
#JsType(isNative=true, package=GLOBAL, name="Object") final class Person {
// you can use getter/setter but as this class is final DTO adds no value
public String firstName; public String lastName; public Phome[] numbers;
// you can add some helper methods, don't forget to skip serialization!
public final #JsOverlay #JsonIgnore List<Phone> getNumberList() {
return Stream.of(numbers).collect(Collectors.toList());
}
}
#JsType(isNative=true, package=GLOBAL, name="Object) final class Phone {
public String number;
}
#JsMethod(namespace = "JSON") public static native <T> T parse(String text);
#Override public void onModuleLoad() {
Person person = parse("{\"firstName\":\"John\",\"lastName\":\"Doe\"}");
GWT.log(person.firstName + " " + person.lastName);
}
These simple and limited DTOs are more a DTO scheme than a type. But has a big advantage, this DTOs works out of the box with most of the server side parsers. Jackson and GSON will encode and parse without any configuration.
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 two java classes as follows
public class A implements Serializable {
private String name;
private List<String> nameList;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getNameList() {
return nameList;
}
public void setNameList(List<String> nameList) {
this.nameList = nameList;
}
}
public class B implements Serializable {
private String name;
private List<String> nameList;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getNameList() {
return nameList;
}
public void setNameList(List<String> nameList) {
this.nameList = nameList;
}
}
Now I have an object of class A, Aobj, with both the fields initialized. I am using BeanUtils.copyProperties(Bobj, Aobj), but only the name field value is copied into the Bobj however Bobj.nameList is null. Is there a way to deep copy a object so that it copies all the fields including Collections like List, Map etc.
I somewhere heard about Dozer, not sure if that is meant for this purpose.
It is a bit strange that you have 2 different classes that are absolutely identical. But regardless, in order to deep copy one to another just write a 2 static methods in some Util class. One method will take class A and return class B and another will take B and return class A. Do your deep copying by yourself. Also, you can create class C that is the same as your classes A and B and then make your classes A and B just empty classes each extending C. It would give you the same structure, but would make your copying logic easier as you can just work with both A and B as instances of C.