How to convert nameless objects to JSON in java (using GSON)? - java

I was writing a program to return JSON object using gson and I discovered something peculiar. Basically when I wanted to convert following object to JSON it gave me null.
Customer customer = new Customer() {
{
setId(1);
setName("Foo bar");
setAddress("Some Address");
}
};
System.out.println(gson.toJson(customer));
where Customer looks like this
public class Customer{
int id;
String name;
String address;
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 getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
but when I created object properly like
Customer customer = new Customer();
customer.setId(1);
customer.setName("Foo bar");
customer.setAddress("Some Address");
System.out.println(gson.toJson(customer));
it worked perfectly fine and gave output as supposed to.
Why does it matter how I create my objects. Is there difference between two methods?

The reason the first case it is returning null because 'customer' object's class is an anonymous one which clazz.isAnonymousClass() return true
See below for GSon implementation

Related

In Java, how do you create an ArrayList, with one element of that list being another ArrayList, that is unique for each element?

So for example.
I have an ArrayList of people. Created through a people object that contains a name, address, age, etc.
How would I then add another list to that, allowing a unique list of hobbies for each person?
So I could have:
James, 32, England, (Football, Tennis)
Chloe, 21, Wales, (Art)
Tried a few things and struggling with it.
import java.util.ArrayList;
public class People {
int id;
String name;
ArrayList<String> hobbies;
public People(int id, String name, ArrayList<String> hobbies) {
this.id = id;
this.name = name;
this.hobbies = hobbies;
}
public People(String name) {
this.name = name;
}
public People() {
// TODO Auto-generated constructor stub
}
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;
}
#Override
public String toString() {
return "People [id=" + id + ", name=" + name + ", hobbies=" + hobbies + "]";
}
}
import java.util.ArrayList;
public class Runner {
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<People> arrayPeople = new ArrayList<>();
ArrayList<String> hobbies = new ArrayList<>();
hobbies.add("Football");
hobbies.add("Tennis");
arrayPeople.add(new People(1,"Paul", hobbies));
hobbies.add("Golf");
arrayPeople.add(new People(2,"James", hobbies));
System.out.println(arrayPeople);
}
}
This creates a hobby list that is the same for each person, not unique.
This creates a hobby list that is the same for each person, not unique.
That's because member hobbies in [Paul] People object has same value as member hobbies in [James] People object, since they are assigned the same value in method main of class Runner. Hence when you change hobbies variable, in method main of class Runner, you are changing for both Paul and James.
The simplest solution is to change the class constructor so that it creates a copy of the hobbies parameter and assigns the copy to the hobbies member:
public People(int id, String name, List<String> hobbies) {
this.id = id;
this.name = name;
this.hobbies = new ArrayList<>(hobbies);
}
However, I suggest that you add methods to class People to manipulate hobbies member, including:
addHobby for adding a hobby
removeHobby for removing a hobby
clearHobbies for removing all hobbies
getHobbies that returns a copy of hobbies (so that code that calls the method cannot change hobbies)
Below code demonstrates.
Note that you should always use the interface – in this case java.util.List – rather than the implementation – in this case ArrayList – in the API so that you can change class People without having to change its API. If you change the API of class People then all other classes that use class People – like class Runner in the code in your question – will need to be changed as well.
import java.util.ArrayList;
import java.util.List;
public class People {
private int id;
private String name;
private List<String> hobbies;
public People(int id, String name, List<String> hobbies) {
this.id = id;
this.name = name;
this.hobbies = new ArrayList<>(hobbies);
}
public People(int id, String name) {
this(id, name, new ArrayList<String>());
}
public People() {
this(0, "");
}
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 void addHobby(String hobby) {
if (!hobbies.contains(hobby)) {
hobbies.add(hobby);
}
}
public void clearHobbies() {
hobbies.clear();
}
public List<String> getHobbies() {
return List.of(hobbies.toArray(new String[]{}));
}
public void removeHobby(String hobby) {
if (hobbies.contains(hobby)) {
hobbies.remove(hobby);
}
}
#Override
public String toString() {
return "People [id=" + id + ", name=" + name + ", hobbies=" + hobbies + "]";
}
public static void main(String[] args) {
List<People> arrayPeople = new ArrayList<>();
People paul = new People(1,"Paul");
paul.addHobby("Football");
paul.addHobby("Tennis");
People james = new People(2,"James");
james.addHobby("Football");
james.addHobby("Tennis");
james.addHobby("Golf");
arrayPeople.add(paul);
arrayPeople.add(james);
System.out.println(arrayPeople);
}
}
Running the above code prints the following:
[People [id=1, name=Paul, hobbies=[Football, Tennis]], People [id=2, name=James, hobbies=[Football, Tennis, Golf]]]
The question seemed unclear to me, however I assume that you created lists such as
[name,age,location]
However, this is not an object. If you create a person object, you can add features inside it. So that when you create a person object, then you will have access to add/edit new features. In your case, your features must be:
Name
Age
Location
List (Whatever you name it, type of it must be an arraylist).
To have a list of people:
class Person{
String name;
int age;
String Address;
...
}
and
ArrayList<Person>
For the people class, if you need each hobby in hobbies to be unique you can have a Set class to store hobbies.
class Person{
String name;
int age;
String address;
Set<String> hobbies;
...
}
If the order does not matter you can use HashSet To maintain the order you can use TreeSet or LinkedHashSet.
class person{
String name;
int age;
String address;
TreeSet<String> hobbies;
...
}
class Person{
String name;
int age;
String address;
LinkedHashSet<String> hobbies;
...
}
To add a hobby to a person.
String hobby = "a hobby";
person.add(hobby);
To add hobbies to a person;
String hobby1 = "hobby1";
String hobby1 = "hobby2";
...
Set<String> hobbies = new TreeSet(); // or Set<String> hobbies = new LinkedHashMap();
hobbies.add(hobby1);
hobbies.add(hobby2);
...
person.addAll(hobby);
For another person with the same hobbies, you need to copy the hobbies, then modifying the hobbies of the second person will not affect the hobbies of the first person.
Set<String> new_hobbies = new TreeSet(old_hobbies); // or new LinkedHashSet(old_hobbies);
another_person.addAll(new_hobbies);

I have to store employee data in a ConcurrentHashMap containing name and id as key and other details as value

Here I have used two ConcurrentHashMaps,
1st map: key = name
value = Employee obj (containing 2nd map)
2nd map: key = id
value = Employee details( pojo class)
But I m doing it wrong. pls someone explain what should be my approach.
here is my code -
import java.util.concurrent.ConcurrentHashMap;
public class POJODemo {
public static void main(String[] args)
{
ConcurrentHashMap <String, Employee> outer_concurrentHashMap = new ConcurrentHashMap<String,Employee>();
Employee empobj = new Employee();
empobj.setId("123");
outer_concurrentHashMap.put("disha", empobj.toString());
System.out.println(outer_concurrentHashMap);
}
}
class Employee
{
public static ConcurrentHashMap <String , POJODetails> inner_concurrentHashMap = new ConcurrentHashMap <String , POJODetails>();
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
POJODetails details = new POJODetails("korba", 12345);
}
class POJODetails{
public POJODetails(String address, int phone) {
super();
this.address = address;
this.phone = phone;
}
private String address;
private int phone;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getPhone() {
return phone;
}
public void setPhone(int phone) {
this.phone = phone;
}
public String toString()
{
return ;
}
}
'outer_concurrentHashMap.put("disha", empobj.toString());' is incorrect; should be 'outer_concurrentHashMap.put("disha", empobj);'
You cannot convert your object to a string and put it in a hash map that only takes employee as a value. When you print the Map it will call.toString on the employee and still print it visibly for you.
When you created your HashMap, you specified that it would take an object of type String as a 'key' and an object of type Employee as a 'value'.
Using HashMap.get('key'), will return an object of type Employee, which is the mapped value to your key. So you could write:
Employee retrievedEmployee = outer_concurrentHashMap.get("disha");
//'retrievedEmployee' has the same value as 'empobj'
In your code, when you write:
outer_concurrentHashMap.put("disha", empobj.toString());
you are not adding an object of type Employee to your hashmap, but the representation of that object as a string.
The correct code would be:
outer_concurrentHashMap.put("disha", empobj);

Calling an object arraylist from another class and iteration through it

I have a problem accessing the arraylist I created in a class. I tried going through the answers of questions similar to mine but unfortunately I was unable to solve the problem.
So I have two classes Student and Person and I want to iterate through the arraylist of Person in the class Student. (The code doesn't really make sense, I know. I just want to understand).
I tried two approaches :
1) creating a variable of type Person in Student class and calling the get method from person class.
2) creating a get method in the class person that returns arraylist.
Both are not working properly when i tried to call the isHere method in the main method.(false was printed instead of true)
I think my two approaches intialise a new array of type Person and not call the arraylist to which elements are already added. How can solve this?
import java.util.ArrayList;
public class Student {
private Person p;
private String name;
private int age;
private String address;
public Student() {
}
public Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public boolean isHere(String name) {
p = new Person();
// I also tried for(Person per : p.getList)
for (Person per : this.getL()) {
if (per.getName().equals(name)) {
System.out.println("hi");
return true;
}
}
return false;
}
public ArrayList<Person> getL() {
return p.getList();
}
public Person getP() {
return p;
}
public void setP(Person p) {
this.p = p;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
The Person class:
import java.util.ArrayList;
public class Person {
private String name;
private ArrayList<Person> list = new ArrayList<Person>();
Person() {
}
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ArrayList<Person> getList() {
return list;
}
public void setList(ArrayList<Person> list) {
this.list = list;
}
public void add(String name) {
list.add(new Person(name));
}
}
The statement p = new Person() in your isHere(..) method is creating a new Person object. When that Person object is created, the name in object p will be null and the list will be empty. So the for loop is never executed as the list is empty and hence it returns false.
If you ever want your code to run, you should not create the Person object and then immediately iterate through it because it will have nothing. You have to either add something to it or use a Person object which you believe will be populated before you run the isHere(..) method

Assign return value to new Variable (Java)

it's been a while since I've done some java coding.
I need to build an application for a business which requires automation (part of a workshop), which is however irrelevant to my question...
I'm stuck on the line : customerList.add(customer); //(part of the addCustomer method in the WCIA class)
Also it's the first time I'm told to "Assign return value to new Variable" as part of an error, so not too sure what that means.
Code: Main
import java.util.ArrayList;
public class WCIA {
private final ArrayList customerList = null;
public static void main(String[] args) {
short s =002;
Customer arno = new Customer();
arno.setName("Arno");
arno.setId(s);
arno.setEmail("arnomeye#gmail.com");
arno.setAddress("Somewhere");
arno.setPhoneNum("0727855201");
System.out.printf("%s",arno.getEmail());
WCIA wcia = new WCIA();
wcia.addCustomer(arno);
wcia.displayCustomers();
}
public void addCustomer (Customer customer)
{
customerList.add(customer); // <---Problem over here
}
public void displayCustomers()
{
for(int x=0;x<customerList.size();x++)
{
Customer cus = (Customer) customerList.get(x);
cus.DisplayCustomer();
}
}
}
Code: Customer class:
public class Customer {
private short id;
private String name;
private String email;
private String phoneNum;
private String address;
public Customer()
{
System.out.println("Class initiated");
}
public void DisplayCustomer()
{
System.out.append("Name : "+ name+"\n");
System.out.append("ID : "+ id+"\n");
System.out.append("Email : "+ email+"\n");
System.out.append("Phone Number : "+ phoneNum+"\n");
System.out.append("address : "+ address+"\n");
}
public void setId(short id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setEmail(String email) {
this.email = email;
}
public void setPhoneNum(String phoneNum) {
this.phoneNum = phoneNum;
}
public void setAddress(String address) {
this.address = address;
}
public short getId() {
return id;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public String getPhoneNum() {
return phoneNum;
}
public String getAddress() {
return address;
}
}
You need to instantiate your ArrayList before you can assign elements to it. You're probably getting a NullPointerException, is my guess.
Change this line:
private final ArrayList customerList = null;
to
private final ArrayList customerList = new ArrayList();
Should solve at least this problem. I did not read the rest of your code so I'm not sure if other problems exist.
customerList is null and never initialized. Create an object of type ArrayList and assign it to that variable before you try to add to it.
You should declare the List with an explicit definition of the type of its elements (parametrized list):
private final List<Customer> customerList;
This way you can get rid of casting to Customer in:
Customer cus = customerList.get(x);
Finally, as good practice, initialize it in the constructor:
public WCIA()
{
customerList = new ArrayList<>();
}

How to get superclass data member from subclass

I'm having trouble accessing a superclass data member from it's subclass.
So I have a superclass Store like this
public class Store {
protected ArrayList<Audiobooks> ab;
public Store(ArrayList<Audiobooks> ab)
{
this.ab = ab;
}
...
}
ab is initialized and everything, then we have a subclass like this
public class Customer extends Store {
...
public Customer(String id, String name, String address)
{
this.id = id;
this.name = name;
this.address = address;
}
public void printAb(){
for(int i = 0; i<ab.size(); i++){
System.out.println(ab.get(i).toString());
}
}
}
I end up getting a null pointer exception error. When the function is placed in the store class it works fine, but when its in the subclass Customer the null pointer exception occurs.
I tried to get it by using super.ab.... but no success.
Thanks for any insight.
Your Customer constructor does not call you Store constructor, so the ab list is never instantiated.
To solve this, you either need to have your customer constructor call the store constructor:
public Customer(String id, String name, String address) {
super(new ArrayList<Audiobooks>());
this.id = id;
this.name = name;
this.address = address;
}
Or have your customer constructor instantiate the list. You also must have more than one constructor for the store class, otherwise the compiler would force you to call the constructor you are showing. You may want to consider getting rid of the empty constructor that you apparently have on the store class if it does not put the class into a valid state.
You access the ab property properly (otherwise you would have a compiler error).
Most likely you are not creating the object anywhere, try doing
protected ArrayList<Audiobooks> ab = new ArrayList<Audiobooks>();
Also, it would be better if you use the most generic interface List
protected List<Audiobooks> ab = new ArrayList<Audiobooks>();
Try doing this.
public class Customer extends Store {
...
public Customer(ArrayList<Audiobooks> a,String id, String name, String address)
{
super(a);
this.id = id;
this.name = name;
this.address = address;
}
public void printAb(){
for(int i = 0; i<ab.size(); i++){
System.out.println(ab.get(i).toString());
}
}
}
or do this
public class Customer extends Store {
...
public Customer(String id, String name, String address)
{
a=new ArrayList<Audiobooks>(/*initial size*/);
this.id = id;
this.name = name;
this.address = address;
}
public void printAb(){
for(int i = 0; i<ab.size(); i++){
System.out.println(ab.get(i).toString());
}
}
}

Categories

Resources