Serialize using Jackson ObjectMapper - java

I am trying to serialize the below ArrayList of GAccount objects using Jackson library with following code:
List<Gaccount> gAccounts;
ObjectMapper mapper=new ObjectMapper();
json=mapper.writeValueAsString(gAccounts);
However, I have noticed that only Id and Name fields are serialized but not properties. Sorry, but I am new to Jackson library. Do I have to manually serialize that field ?
package in.co.madhur.ganalyticsdashclock;
import java.util.ArrayList;
import java.util.List;
public class GAccount
{
private String Id;
private String Name;
private List<GProperty> properties=new ArrayList<GProperty>();
public GAccount(String Id, String Name)
{
this.Id=Id;
this.Name=Name;
}
public String getName()
{
return Name;
}
public void setName(String name)
{
Name = name;
}
public String getId()
{
return Id;
}
public void setId(String id)
{
Id = id;
}
List<GProperty> getProperties()
{
return properties;
}
void setProperties(List<GProperty> properties)
{
this.properties = properties;
}
#Override
public String toString()
{
return Name;
}
}

The default visibility is to use all public getter methods and all public properties. If you make the getter this:
public List<GProperty> getProperties()
it should work.
You could also change the auto-detection defaults, but it's overkill here. See http://www.cowtowncoder.com/blog/archives/2011/02/entry_443.html for more info.

I am using jackson 2.9.0. The default visibility is always 'false' to all the members. In this case, we alway need to use a different visibility, otherwise the result json string will be empty. Here is the code extracted from JsonAutoDetect
public boolean isVisible(Member m) {
switch(this) {
case ANY:
return true;
...
case PUBLIC_ONLY:
return Modifier.isPublic(m.getModifiers());
default:
return false;
}
}

Related

Hiding protected fields from Jackson serialization

For some reason I am not able to hide protected fields (without setter), via ObjectMapper configuration, from being serialized to a JSON string.
My POJO:
public class Item {
protected String sn;
private String name;
public Item(){
sn = "43254667";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSn() {
return sn;
}
}
My mapper:
mapper.setVisibility(PropertyAccessor.SETTER, Visibility.PUBLIC_ONLY);
mapper.setVisibility(PropertyAccessor.GETTER, Visibility.PUBLIC_ONLY);
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.NONE);
The output is:
{
"sn" : "43254667",
"name" : "abc"
}
UPDATE: I cannot modify the Item class, hence I cannot use annotations.
Use #JsonIgnore
You could annotate the field or method with #JsonIgnore.
It's a marker annotation that indicates that the annotated method or field is to be ignored by introspection-based serialization and deserialization functionality.
Use as following:
public class Item {
#JsonIgnore
protected String sn;
...
}
Or as following:
public class Item {
...
#JsonIgnore
public String getSn() {
return sn;
}
}
Use #JsonIgnore with mix-ins
Based on your comment, you could use mix-in annotations when modifying the classes is not an option, as described in this answer.
You can think of it as kind of aspect-oriented way of adding more annotations during runtime, to augment statically defined ones.
First, define a mix-in annotation interface (class would do as well):
public interface ItemMixIn {
#JsonIgnore
String getSn();
}
Then configure your ObjectMapper to use the defined interface as a mix-in for your POJO:
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(Item.class, ItemMixIn.class);
For extra details, check the documentation.
Use a BeanSerializerModifier
Based on your comment, you may consider a BeanSerializerModifier, as following:
public class CustomSerializerModifier extends BeanSerializerModifier {
#Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
// In this method you can add, remove or replace any of passed properties
return beanProperties;
}
}
Then register the custom serializer as a module in your ObjectMapper.
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new SimpleModule() {
#Override
public void setupModule(SetupContext context) {
super.setupModule(context);
context.addBeanSerializerModifier(new CustomSerializerModifier());
}
});
You've instructed your mapper to serialize public getters:
mapper.setVisibility(PropertyAccessor.GETTER, Visibility.PUBLIC_ONLY);
That's why Jackson will serialize the sn field (You have a public getter here in the end).
To get rid of the serialized sn field, simply annotate your getter with #JsonIgnore:
public class Item{
protected String sn;
private String name;
public Item(){
sn = "43254667";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#JsonIgnore
public String getSn() {
return sn;
}
}
If you cannot annotate your class, you can always write a custom serializer for your POJO or use Mixins

jackson serialization of nested objects

I have problem with jackson serialization of object by its interface.
I have class
class Point implements PointView {
private String id;
private String name;
public Point() {
}
public Point(String id, String name) {
this.id = id;
this.name = name;
}
#Override
public String getId() {
return id;
}
public String getName() {
return name;
}
}
which implements
interface PointView {
String getId();
}
and have class
class Map implements MapView {
private String id;
private String name;
private Point point;
public Map() {
}
public Map(String id, String name, Point point) {
this.id = id;
this.name = name;
this.point = point;
}
#Override
public String getId() {
return id;
}
public String getName() {
return name;
}
#JsonSerialize(as = PointView.class)
public Point getPoint() {
return point;
}
}
which implements
interface MapView {
String getId();
Point getPoint();
}
And have class
class Container {
private Map map;
public Container() {
}
public Container(Map map) {
this.map = map;
}
#JsonSerialize(as = MapView.class)
public Map getMap() {
return map;
}
}
I want serialize Container with Jackson and get result
{"map":{"id":"mapId","point":{"id":"pointId"}}}
But in fact I get result
{"map":{"id":"mapId","point":{"id":"pointId","name":"pointName"}}}
that have property "name" in nested object "point" although I specified serializition type of Point in Map (#JsonSerialize(as = PointView.class)). Interface PointView dont have method getName, but in result exists field "name" of Point.
If I remove annotation (#JsonSerialize(as = MapView.class)) from method getMap in class Container I get result
{"map":{"id":"mapId","name":"mapName","point":{"id":"pointId"}}}
Now point dont have property "name", but map have.
How can I get result
{"map":{"id":"mapId","point":{"id":"pointId"}}}
?
To get the desired result also the same method in interface must be annotated by #JsonSerialize
interface MapView {
String getId();
#JsonSerialize(as = PointView.class)
Point getPoint();
}
You can annotate the method like this:
#JsonIgnore
public String getName() {
return name;
}
Or if you want specific serialization in this use case, but normal serialization in others, you can use a #JsonView (see doc).
The reason it's serializing out the name is that the instance has the accessor getName(), even though interface does not.
Yes, you can use
#JsonSerialize(as=MyInterface.class)
public class ConcreteClass implements MyInterface { .... }
either on implementation class (as above), or on property that has value.

Parsing nested objects with Jackson

I am using Robospice + Retrofit + Jackson. I have not plain class which has another class object as a field. I need to parse json and create class with field.
Here is my class
#JsonIgnoreProperties(ignoreUnknown=true)
public class User implements UserInformationProvider {
#JsonProperty("customer_id")
public int id;
#JsonProperty("firstname")
public String firstName;
#JsonProperty("lastname")
public String lastName;
#JsonProperty("email")
public String email;
#JsonProperty("telephone")
public String phone;
#JsonProperty("token_api")
public String token;
#JsonProperty("token_expire")
public int tokenExpireTime;
public UserPreferences userPreferences;
#Override
public String getUserFirstName() {
return firstName;
}
#Override
public String getUserLastName() {
return lastName;
}
#Override
public String getUserEmail() {
return email;
}
#Override
public String getUserIconUrl() {
return null;
}
}
And preferences class
public class UserPreferences {
public boolean offersNotifications;
public boolean statusChangedNotifications;
public boolean subscriptionNotifications;
#JsonProperty("new_offers")
public boolean newOffersNotify;
#JsonProperty("order_status_changed")
public boolean orderStatusChangedNotify;
#JsonProperty("hot_offers")
public boolean hotOffersNotify;
}
Request that I need to parse into POJO.
{
"customer_id": 84,
"token_api": "ef5d7d2cd5dfa27a",
"token_expire_unix": "1435113663",
"preferences": {
"new_offers": "1",
"order_status_changed": "1",
"hot_offers": "1"
}
}
Please help, how can I do this using Jackson. I would be very grateful for any help. Thanks in advance.
The main problem lies inside of UserPreferences. Right now your code is attempting to deserialize "1" as a boolean. Java will not do this translation for you, so you will need to create a custom deserializer and apply it to the fields with numeric booleans.
Create a Custom Deserializer
A deserializer allows you to specify a class and apply custom operations to how it is created from JSON:
public class NumericBooleanDeserializer extends JsonDeserializer<Boolean> {
#Override
public Boolean deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
int intValue = p.getValueAsInt();
switch (intValue) {
case 0:
return Boolean.TRUE;
case 1:
return Boolean.FALSE;
default:
// throw exception or fail silently
}
return null; // can throw an exception if failure is desired
}
}
Apply Custom Deserialization to Fields
Since you probably don't want to register this on your ObjectMapper and apply it to all deserialization, you can use the #JsonDeserialize annotation. Your UserPreferences class will end up looking something like this:
public class UserPreferences {
public boolean offersNotifications;
public boolean statusChangedNotifications;
public boolean subscriptionNotifications;
#JsonProperty("new_offers")
#JsonDeserialize(using = NumericBooleanDeserializer.class)
public boolean newOffersNotify;
#JsonProperty("order_status_changed")
#JsonDeserialize(using = NumericBooleanDeserializer.class)
public boolean orderStatusChangedNotify;
#JsonProperty("hot_offers")
#JsonDeserialize(using = NumericBooleanDeserializer.class)
public boolean hotOffersNotify;
}
Make Sure #JsonProperty Matches JSON Keys
Since your JSON has "preferences" and the name of your Java property is userPreferences you will need to slap a #JsonProperty("preferences") on the property inside of User

Deserializing JSON wrapper object with list returns null properties

I got json like below:
{"examinationTypes":[{"ExaminationTypeVO":{"id":1,"name":"Badanie krwi"}},{"ExaminationTypeVO":{"id":2,"name":"Spirometria"}},{"ExaminationTypeVO":{"id":3,"name":"Wymaz"}},{"ExaminationTypeVO":{"id":4,"name":"Ciśnienie"}},{"ExaminationTypeVO":{"id":5,"name":"EKG"}},{"ExaminationTypeVO":{"id":6,"name":"Elektrowstrząsy"}},{"ExaminationTypeVO":{"id":7,"name":"Tomografia"}},{"ExaminationTypeVO":{"id":8,"name":"Lewatywa"}},{"ExaminationTypeVO":{"id":9,"name":"Aneskopia"}},{"ExaminationTypeVO":{"id":10,"name":"Rektoskopia"}},{"ExaminationTypeVO":{"id":11,"name":"Kolonoskopioa"}},{"ExaminationTypeVO":{"id":12,"name":"Echo serca"}},{"ExaminationTypeVO":{"id":13,"name":"Ablacja"}},{"ExaminationTypeVO":{"id":14,"name":"Badnaie dopplerowskie"}},{"ExaminationTypeVO":{"id":15,"name":"Kapilaroskopia"}}]}
I have defined types:
#JsonRootName(value="ExaminationTypeVO")
#JsonIgnoreProperties(ignoreUnknown = true)
public class ExaminationTypeVO {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and
public class ExaminationTypesVO {
private List<ExaminationTypeVO> examinationTypes;
public List<ExaminationTypeVO> getExaminationTypes() {
return examinationTypes;
}
public void setExaminationTypes(List<ExaminationTypeVO> examinationTypes) {
this.examinationTypes = examinationTypes;
}
When I am deserializing it like that:
ExaminationTypesVO l = m.readValue(result, ExaminationTypesVO.class);
I receive an wrapper object but the list inside contains objects of type ExaminationTypeVO with all properties set to null.
Can anybody help to figure it out?
Your issue is that you have an extra level of object that you are trying to deserialize. Trying to not be confusing as I explain this: you have an array of objects, those objects contain a single ExaminationTypeVO object.
If you are stuck with the structure of the JSON that you provided, then you will need to add another "level" to your deserialization. You can do this via a wrapper object inside of your ExaminationTypesVO class:
public class ExaminationTypesVO {
private List<ExaminationTypeVOWrapper> examinationTypes;
public List<ExaminationTypeVOWrapper> getExaminationTypes() {
return examinationTypes;
}
public void setExaminationTypes(List<ExaminationTypeVOWrapper> examinationTypes) {
this.examinationTypes = examinationTypes;
}
public static class ExaminationTypeVOWrapper {
private final ExaminationTypeVO examinationTypeVO;
#JsonCreator
public ExaminationTypeVOWrapper(#JsonProperty("ExaminationTypeVO") ExaminationTypeVO examinationTypeVO) {
this.examinationTypeVO = examinationTypeVO;
}
public ExaminationTypeVO getExaminationTypeVO() {
return examinationTypeVO;
}
}
}
If you have control over the JSON that you are deserializing, you can just remove the extra "level" (ExaminationTypeVO wrapping object) and not have to change your code. Your new JSON in this approach would look like:
{
"examinationTypes": [
{
"id": 1,
"name": "Badanie krwi"
}, ...
]
}
With either of these approaches you can remove both of the class-level annotations you have on ExaminationTypeVO.

How to create a POJO?

Recently I've started hearing about "POJOs" (Plain Old Java Objects). I googled it, but still don't understand the concept well. Can anyone give me a clear description of a POJO?
Consider a class "Person" with variables "id, name, address, salary" -- how would I create a POJO for this scenario? Is the code below a POJO?
public class Person {
//variables
People people = new People();
private int id;
private String name;
private String address;
private int salary;
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
public int getSalary() {
return salary;
}
public void setId() {
this.id = id;
}
public void setName() {
this.name = name;
}
public void setAddress() {
this.address = address;
}
public void setSalary() {
this.salary = salary;
}
}
A POJO is just a plain, old Java Bean with the restrictions removed. Java Beans must meet the following requirements:
Default no-arg constructor
Follow the Bean convention of getFoo (or isFoo for booleans) and setFoo methods for a mutable attribute named foo; leave off the setFoo if foo is immutable.
Must implement java.io.Serializable
POJO does not mandate any of these. It's just what the name says: an object that compiles under JDK can be considered a Plain Old Java Object. No app server, no base classes, no interfaces required to use.
The acronym POJO was a reaction against EJB 2.0, which required several interfaces, extended base classes, and lots of methods just to do simple things. Some people, Rod Johnson and Martin Fowler among them, rebelled against the complexity and sought a way to implement enterprise scale solutions without having to write EJBs.
Martin Fowler coined a new acronym.
Rod Johnson wrote "J2EE Without EJBs", wrote Spring, influenced EJB enough so version 3.1 looks a great deal like Spring and Hibernate, and got a sweet IPO from VMWare out of it.
Here's an example that you can wrap your head around:
public class MyFirstPojo
{
private String name;
public static void main(String [] args)
{
for (String arg : args)
{
MyFirstPojo pojo = new MyFirstPojo(arg); // Here's how you create a POJO
System.out.println(pojo);
}
}
public MyFirstPojo(String name)
{
this.name = name;
}
public String getName() { return this.name; }
public String toString() { return this.name; }
}
POJO:- POJO is a Java object not bound by any restriction other than those forced by the Java Language Specification.
Properties of POJO
All properties must be public setter and getter methods
All instance variables should be private
Should not Extend prespecified classes.
Should not Implement prespecified interfaces.
Should not contain prespecified annotations.
It may not have any argument constructors
Example of POJO
public class POJO {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
A POJO is a Plain Old Java Object.
From the wikipedia article I linked to:
In computing software, POJO is an
acronym for Plain Old Java Object. The
name is used to emphasize that a given
object is an ordinary Java Object, not
a special object, and in particular
not an Enterprise JavaBean
Your class appears to already be a POJO.
POJO class acts as a bean which is used to set and get the value.
public class Data
{
private int id;
private String deptname;
private String date;
private String name;
private String mdate;
private String mname;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDeptname() {
return deptname;
}
public void setDeptname(String deptname) {
this.deptname = deptname;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMdate() {
return mdate;
}
public void setMdate(String mdate) {
this.mdate = mdate;
}
public String getMname() {
return mname;
}
public void setMname(String mname) {
this.mname = mname;
}
}
When you aren't doing anything to make your class particularly designed to work with a given framework, ORM, or other system that needs a special sort of class, you have a Plain Old Java Object, or POJO.
Ironically, one of the reasons for coining the term is that people were avoiding them in cases where they were sensible and some people concluded that this was because they didn't have a fancy name. Ironic, because your question demonstrates that the approach worked.
Compare the older POD "Plain Old Data" to mean a C++ class that doesn't do anything a C struct couldn't do (more or less, non-virtual members that aren't destructors or trivial constructors don't stop it being considered POD), and the newer (and more directly comparable) POCO "Plain Old CLR Object" in .NET.
According to Martin Fowler
The term was coined while Rebecca Parsons, Josh MacKenzie and I were preparing for a talk at a conference in September 2000. In the talk, we were pointing out the many benefits of encoding business logic into regular java objects rather than using Entity Beans. We wondered why people were so against using regular objects in their systems and concluded that it was because simple objects lacked a fancy name. So we gave them one, and it’s caught on very nicely.
Generally, a POJO is not bound to any restriction and any Java object can be called a POJO but there are some directions. A well-defined POJO should follow below directions.
Each variable in a POJO should be declared as private.
Default constructor should be overridden with public accessibility.
Each variable should have its Setter-Getter method with public accessibility.
Generally POJO should override equals(), hashCode() and toString() methods of Object (but it's not mandatory).
Overriding compare() method of Comparable interface used for sorting (Preferable but not mandatory).
And according to Java Language Specification, a POJO should not have to
Extend pre-specified classes
Implement pre-specified interfaces
Contain pre-specified annotations
However, developers and frameworks describe a POJO still requires the use prespecified annotations to implement features like persistence, declarative transaction management etc. So the idea is that if the object was a POJO before any annotations were added would return to POJO status if the annotations are removed then it can still be considered a POJO.
A JavaBean is a special kind of POJO that is Serializable, has a no-argument constructor, and allows access to properties using getter and setter methods that follow a simple naming convention.
Read more on Plain Old Java Object (POJO) Explained.
there are mainly three options are possible for mapping purpose
serialize
XML mapping
POJO mapping.(Plain Old Java Objects)
While using the pojo classes,it is easy for a developer to map with the database.
POJO classes are created for database and at the same time value-objects classes are created with getter and setter methods that will easily hold the content.
So,for the purpose of mapping in between java with database, value-objects and POJO classes are implemented.
import java.io.Serializable;
public class Course implements Serializable {
protected int courseId;
protected String courseName;
protected String courseType;
public Course() {
courseName = new String();
courseType = new String();
}
public Course(String courseName, String courseType) {
this.courseName = courseName;
this.courseType = courseType;
}
public Course(int courseId, String courseName, String courseType) {
this.courseId = courseId;
this.courseName = courseName;
this.courseType = courseType;
}
public int getCourseId() {
return courseId;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public String getCourseType() {
return courseType;
}
public void setCourseType(String courseType) {
this.courseType = courseType;
}
#Override
public int hashCode() {
return courseId;
}
#Override
public boolean equals(Object obj) {
if (obj != null || obj instanceof Course) {
Course c = (Course) obj;
if (courseId == c.courseId && courseName.equals(c.courseName)
&& courseType.equals(c.courseType))
return true;
}
return false;
}
#Override
public String toString() {
return "Course[" + courseId + "," + courseName + "," + courseType + "]";
}
}
public class UserInfo {
String LoginId;
String Password;
String FirstName;
String LastName;
String Email;
String Mobile;
String Address;
String DOB;
public String getLoginId() {
return LoginId;
}
public void setLoginId(String loginId) {
LoginId = loginId;
}
public String getPassword() {
return Password;
}
public void setPassword(String password) {
Password = password;
}
public String getFirstName() {
return FirstName;
}
public void setFirstName(String firstName) {
FirstName = firstName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String lastName) {
LastName = lastName;
}
public String getEmail() {
return Email;
}
public void setEmail(String email) {
Email = email;
}
public String getMobile() {
return Mobile;
}
public void setMobile(String mobile) {
Mobile = mobile;
}
public String getAddress() {
return Address;
}
public void setAddress(String address) {
Address = address;
}
public String getDOB() {
return DOB;
}
public void setDOB(String DOB) {
this.DOB = DOB;
}
}
File-setting-plugins-Browse repositories
Search RoboPOJOGenerator and install, Restart Android studio
Open Project and right click on package select on Generate POJO from JSON
Paste JSON in dialogbox and select option according your requirements
Click on Generate button
If a class is not bogged down from a framework or a library, then an object created from that class is recognized as a POJO.
Let's see some examples:
class MyServlet extends HttpServlet{
//....
}
The sole meaning of MyServlet class is given by the HttpServlet class. Therefore the objects created from the MyServlet are not POJOs.
class MyClass implements Serializable{
//...
}
The Serializable interface does not give a meaning to the class MyClass. Therefore the objects created from the MyClass are POJOs.

Categories