Hello I was wondering how I can make the most dynamic get set methods in a java program I am working on? The program has multiple fields and each field needs to have its own get and set method but I want only one get set method that can get and set any field in the class I want.
package kalsi;
public class ContestantInformation {
String firstName, lastName, city, province, postalCode, streetName, streetNumber, phoneNum, birthDate;
public ContestantInformation() {
}
public ContestantInformation(String firstName, String lastName, int streetNumber, String streetName, String city,
String province, String postalCode, int phoneNum, int birthDate) {
this.firstName = firstName;
this.lastName = lastName;
this.birthDate = "" + birthDate;
this.streetNumber = "" + streetNumber;
this.streetName = streetName;
this.city = city;
this.postalCode = postalCode;
this.phoneNum = "" + phoneNum;
}
public void setName(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
You can use your IDE to generate getter/setter methods. If you are using eclipse then you can do it by going to Source>generate methods.
Or alternatively you can use lombok generate getter setter method dynamically. In this case you don't even need to write your getter/setter methods. Look at the example -
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
public class Person {
#Getter #Setter private String name;
#Getter #Setter private int age = 10;
}
Related
having class, the data goes into the map
#Getter
#ToString
#Builder
//#FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
//#JsonIgnoreProperties(value = {"firstName", "lastName"})
public class User {
// #JsonProperty("id")
private final UUID userUid;
#JsonIgnore
private final String firstName;
#JsonIgnore
private final String lastName;
private final Gender gender;
private final Integer age;
private final String email;
public enum Gender {
MALE, FEMALE
}
public String getFullName() {
return this.firstName + " " + this.lastName;
}
public int getDateOfBirth() {
return LocalDate.now().minusYears(age).getYear();
}
public User(#JsonProperty("userUid") UUID userUid
, #JsonProperty("firstName") String firstName
, #JsonProperty("lastName") String lastName
, #JsonProperty("gender") Gender gender
, #JsonProperty("age") Integer age
, #JsonProperty("email") String email) {
this.userUid = userUid;
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.age = age;
this.email = email;
}
public static User newUser(UUID userUid, User user) {
return User.builder()
.userUid(userUid)
.firstName(user.getFirstName())
.lastName(user.getLastName())
.gender(user.getGender())
.age(user.getAge())
.email(user.email)
.build();
}
}
#JsonIgnore annotations on the field do not work, the fields are displayed in the response.
the data is hidden when I annotate class by #JsonIgnoreProperties or by adding annotations over the getter.
and #JsonProperty above the field generally throws a 500 error ...
It turns out that jackson annotations with lombok #Getter do not work, and it is necessary to annotate getters, or am I doing something wrong?
You can assign attribute access of #JsonProperty to JsonProperty.Access.WRITE_ONLY in order to be able to receive this property but exclude it while serializing a POJO.
#Getter
#ToString
#Builder
public static class User {
private final UUID userUid;
private final String firstName;
private final String lastName;
private final Gender gender;
private final Integer age;
private final String email;
public User(#JsonProperty("userUid") UUID userUid,
#JsonProperty(value = "firstName", access = JsonProperty.Access.WRITE_ONLY)
String firstName,
#JsonProperty(value = "lastName", access = JsonProperty.Access.WRITE_ONLY)
String lastName,
#JsonProperty("gender") Gender gender,
#JsonProperty("age") Integer age,
#JsonProperty("email") String email) {
this.userUid = userUid;
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.age = age;
this.email = email;
}
// the rest code
}
Usage example:
String user = mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(
User.builder()
.userUid(new UUID(1, 1))
.firstName("firstName")
.lastName("lastName")
.gender(User.Gender.MALE)
.age(1000)
.email("email#example.com")
.build()
);
System.out.println(user);
Output:
{
"userUid" : "00000000-0000-0001-0000-000000000001",
"gender" : "MALE",
"age" : 1000,
"email" : "email#example.com",
"fullName" : "firstName lastName",
"dateOfBirth" : 1022
}
Note: there are no attributes firstName and lastName, but instead fullName is present because of the public method getFullName() which would be treated by Jackson as a plain getter (I'm sure that was precisely the original intention of the OP, but it's worth to draw the reader's attention to this fact)
Address class:
public class Address {
private String country;
private String county;
private String city;
private String postcode;
private String HouseNumber;
public Address(String country, String county, String city, String postcode, String HouseNumber) {
this.country = country;
this.county = county;
this.city = city;
this.postcode = postcode;
this.HouseNumber = HouseNumber;
}
public void view_adress() {
String[] address = {country, county, city, postcode, HouseNumber};
for (int i = 0; i<address.length; i++) {
System.out.println(address[i]);
}
}
public void viewHouseNumber() {
System.out.print(HouseNumber);
}
}
Person class:
public class Person {
private String firstName;
private String lastName;
private String Date_of_birth;
private String PhoneNumber;
private String[] address;
public Person (String firstName, String lastName, String Date_of_birth, String PhoneNumber, String[] address) {
this.firstName = firstName;
this.lastName = lastName;
this.Date_of_birth = Date_of_birth;
this.PhoneNumber = PhoneNumber;
this.address = address;
}
public void view_PhoneNumber() {
System.out.print(PhoneNumber);
}
}
Make use of OOP Composition.
public class Person {
//...
List<Address> addresses;
//...
}
One instance of a Person will have a 0 or more instances of Address.
Note, that in a real world scenario, you better want to retain a list of userIds in your Address class as well, because, more-than-one users, might have one, or also more-than-one addresses, which means, that that your relation must be Many-To-Many.
No less (at all) important thing it to stick with the Java Naming Conventions and name:
classes with PascalCase;
fields and method names with camelCase;
constants with ALL_CAPS_SEPARATED_WITH_UNDERSCORES.
I am using Java 8 to perform this task. I also following dependency work with JDK8 datatypes.
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
<version>2.6.3</version>
</dependency>
I have a class that looks like
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Optional;
public class Person {
private String firstName;
private String lastName;
private int age;
private Optional<Address> address;
private Optional<String> phone;
private Person() {
}
public Person(String firstName, String lastName, int age) {
this(firstName, lastName, age, Optional.empty(), Optional.empty());
}
public Person(String firstName, String lastName, int age,
Optional<Address> address, Optional<String> phone) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.address = address;
this.phone = phone;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
#JsonIgnore
public Optional<Address> getAddress() {
return address;
}
#JsonIgnore
public Optional<String> getPhone() {
return phone;
}
#JsonProperty("address")
private Address getAddressForJson(){
return address.orElse(null);
}
#JsonProperty("phone")
private String getPhoneForJson() {
return phone.orElse(null);
}
}
and
public class Address {
private String street;
private String city;
private String state;
private int zip;
private String country;
public Address(String street, String city, String state, int zip, String country) {
this.street = street;
this.city = city;
this.state = state;
this.zip = zip;
this.country = country;
}
public String getStreet() {
return street;
}
public String getCity() {
return city;
}
public String getState() {
return state;
}
public int getZip() {
return zip;
}
public String getCountry() {
return country;
}
}
I write a test to write a valid Person object to a file and and read it back to a Person object. My test is
#Test
public void writeAndReadPersonAsJsonOnFile() throws Exception {
Address address = new Address("1 Infinite Loop", "Cupertino", "CA", 95014, "USA");
String phone = "1-800-My-Apple";
Person person = new Person("john", "doe", 21, Optional.of(address), Optional.of(phone));
ObjectMapper objectMapper = registerJdkModuleAndGetMapper();
File file = temporaryFolder.newFile("person.json");
objectMapper.writeValue(file, person);
assertTrue(file.exists());
assertTrue(file.length() > 0);
Person personFromFile = objectMapper.readValue(file, Person.class);
assertEquals(person, personFromFile);
}
private ObjectMapper registerJdkModuleAndGetMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new Jdk8Module());
return objectMapper;
}
The file created as part of test has following contents
{
"firstName": "john",
"lastName": "doe",
"age": 21,
"address": {
"street": "1 Infinite Loop",
"city": "Cupertino",
"state": "CA",
"zip": 95014,
"country": "USA"
},
"phone": "1-800-My-Apple"
}
But when reading back, I get personFromFile which looks like following
personFromFile = {Person#1178}
firstName = "john"
lastName = "doe"
age = 21
address = null
phone = null
as you can see, the address and phone they both are null, even though they are present in the file.
What is wrong here?
UPDATE
The codebase is https://github.com/101bits/java8-optional-json. This also contains the failing test
Try marking one of the constructors with #JsonCreator to tell Jackson which constructor to use. Note: this also requires you to mark each of the constructor's parameters with #JsonProperty
You should use the #JsonCreator annotation when you want Jackson to constructor objects with a constructor or factory method as opposed letting Jackson use setters or public (non-final) fields
Additionally, your test will not pass until you override "equals" for both Person and Address
public class Person {
private String firstName;
private String lastName;
private int age;
private Optional<Address> address;
private Optional<String> phone;
public Person(String firstName, String lastName, int age) {
this(firstName, lastName, age, Optional.empty(), Optional.empty());
}
#JsonCreator
public Person(
#JsonProperty("firstName") String firstName,
#JsonProperty("lastName") String lastName,
#JsonProperty("age") int age,
#JsonProperty("address") Optional<Address> address,
#JsonProperty("phone") Optional<String> phone) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.address = address;
this.phone = phone;
}
Update: Pull Request with passing tests
As far as i have read optional does not get serialized and hence, while deserializing you wont get the value if you are using default java serialization. However, if you are using your serialization, it should be fine.
Refer this link for more details:
Why java.util.Optional is not Serializable, how to serialize the object with such fields
Actually i am implementing one program in which i am retrieving information from database and i am setting that info to One Object using setters and i just want to print that Object parameters without using system.out.println(object.getHeadCount());
I just want like if i am giving system.out.println(object); so using this code it should print data in Json format or any other readable format.
How to do it.Because my object is containing 30 fields so it is very hectic to write 30 getters to print data.
You have to override toString()
Normal way
class User {
private String firstName;
private String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
#Override
public String toString(){
return this.firstName + " " + this.lastName;
}
}
Using Apache Commons
class User {
private String firstName;
private String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
#Override
public String toString(){
return new ToStringBuilder(this)
.append("firstName", firstName)
.append("lastName", lastName)
.toString();
}
}
Using Google Guava
class User {
private String firstName;
private String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
#Override
public String toString(){
return MoreObjects.toStringHelper(this)
.add("firstName", firstName)
.add("lastName", lastName)
.toString();
}
}
You simply have to override the toString() method of the class, read about it in java doc for Object class. Most IDE support it's automatic generation for all the fields of your class or for a number of them. Just for example:
class User {
private String name;
private String surname;
User(String name, String surname)
{
this.name = name;
this.surname = surname;
}
#Override
public String toString()
{
return this.name+" "+this.surname;
}
}
You should override toString() method. if you are using eclipse then you can try right-click within the editor, you'll find it under Source -> Generate toString()
To make a toString method you can simply just add one like so.
public String toString(){
return "" + getValue();
}
The toString method is a part of
java.lang.Object
So it is implemented in every class.
I've built a Java application for, globally, mange computers database at my job. At first, I've been told that we needed a tab called 'Users', which would contain first name, last name and email. But now, the technician wants to add other fields such as address, phone, etc. He asked me if he could add himself these fields. The problem is, he's not a programmer. He wants to add these fields with a GUI. I have built the application with static fields, and here is my User Class.
public class User {
private String firstname;
private String lastname;
private String email;
private int id;
public User(String firstname, String lastname) {
this.firstname = firstname;
this.lastname = lastname;
}
public User(int id, String firstname, String lastname, String email) {
this.id = id;
this.firstname = firstname;
this.lastname = lastname;
this.email = email;
}
public User(String firstname, String lastname, String email) {
this.firstname = firstname;
this.lastname = lastname;
this.email = email;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getId() {
return id;
}
public String toString() {
return firstname + " " + lastname;
}
}
Now, I wonder if there's a way to modify this class using the GUI or if I have to rebuild entirely the software and stop using object classes like that. There are also classes like "Software" and "Operating Systems" that have static fields but need to be modified if necessary.
I don't know what options exactly I have to get the job done:
Let the tech modify the database and do something like "for each column in database, add this column in the GUI". (Which would cause to rebuild the entire software.)
others?
Any reads/tutorials on that kind of issues?
Thanks.
If the requirement is that a normal user should be able to add additonal fields to existing objects, propably the best way would be to store the information in a map.
So instead of:
public class User {
private String firstname;
private String lastname;
private String email;
private int id;
}
you would have:
public class User {
private int id;
private Map<String,String> properties;
public User(String firstname, String lastname) {
properties = new HashMap<String,String>();
properties.put("firstname",firstname);
properties.put("lastname",lastname);
}
etc.