Json Jackson deserialization without inner classes - java

I have a question concerning Json deserialization using Jackson.
I would like to deserialize a Json file using a class like this one:
(taken from http://wiki.fasterxml.com/JacksonInFiveMinutes)
public class User
{
public enum Gender { MALE, FEMALE };
public static class Name {
private String _first, _last;
public String getFirst() { return _first; }
public String getLast() { return _last; }
public void setFirst(String s) { _first = s; }
public void setLast(String s) { _last = s; }
}
private Gender _gender;
private Name _name;
private boolean _isVerified;
private byte[] _userImage;
public Name getName() { return _name; }
public boolean isVerified() { return _isVerified; }
public Gender getGender() { return _gender; }
public byte[] getUserImage() { return _userImage; }
public void setName(Name n) { _name = n; }
public void setVerified(boolean b) { _isVerified = b; }
public void setGender(Gender g) { _gender = g; }
public void setUserImage(byte[] b) { _userImage = b; }
}
A Json file can be deserialized using the so called "Full Data Binding" in this way:
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(new File("user.json"), User.class);
My problem is the usage of the inner class "Name". I would like to do the same thing without using inner classes. The "User" class would became like that:
import Name;
import Gender;
public class User
{
private Gender _gender;
private Name _name;
private boolean _isVerified;
private byte[] _userImage;
public Name getName() { return _name; }
public boolean isVerified() { return _isVerified; }
public Gender getGender() { return _gender; }
public byte[] getUserImage() { return _userImage; }
public void setName(Name n) { _name = n; }
public void setVerified(boolean b) { _isVerified = b; }
public void setGender(Gender g) { _gender = g; }
public void setUserImage(byte[] b) { _userImage = b; }
}
This means to find a way to specify to the mapper all the required classes in order to perform the deserialization.
Is this possible? I looked at the documentation but I cannot find any solution.
My need comes from the fact that I use the Javassist library to create such classes, and it does not support inner or anonymous classes.
Thank you in advance

There should be no difference between the static inner class Name, and the top-level class of the same name. The Jackson runtime should not be able to meaningfully distinguish between the two situations.
Have you tried moving the Name class out of User, changing it into a top-level class? It should still work as before.
edit: I just tried this, and it works fine when Name is a top-level class. The example had it as an inner class for the sake of brevity, I suspect.

mr. Skaffman's answer is right on. The only additional thing to mention is that unlike JAXB, Jackson does not generally require you to specify classes you operate on, except for the root class (and not always even that, if you use Polymorphic Handling).

Related

how to create a List type of non public class from another package?

My Package A has one java file with 2 classes. Login class which is public and LoginDetails class which cannot be public because it is in the same file. how to create a List of LoginDetails type from Package B.
package A;
public class Login {
private String name;
private String passWord;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
#Override
public String toString() {
return "Login [name=" + name + ", passWord=" + passWord + "]";
}
}
class LoginDetails{
public LoginDetails(int id, int geight) {
super();
this.id = id;
this.geight = geight;
}
private int id;
private int geight;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getGeight() {
return geight;
}
public void setGeight(int geight) {
this.geight = geight;
}
public void hidden() {
System.out.println("From hidden");
}
public LoginDetails() {
}
}
package B;
import java.util.ArrayList;
import java.util.List;
public class Demo {
public static void main(String[] args) throws Exception {
List<LoginDetails> l = new ArrayList<LoginDetails>();
}
}
A solution to your weird question which doesnt include changing neither of the Login nor LoginDetails classes would be by adding a second Public class called AUtils such like this:
AUtils/AFactory class
package A;
import java.util.ArrayList;
public class AUtils {
public static ArrayList<LoginDetails> generateList(){
return new ArrayList<LoginDetails>();
}
public static ArrayList<LoginDetails> generateListWithInitialSize(int x){
return new ArrayList<LoginDetails>(x);
}
public static LoginDetails generateAnObject(){
return new LoginDetails();
}
public static LoginDetails generateWithData(int id, int geight){
return new LoginDetails(id,geight);
}
}
And your Demo would look like this:
public class Demo {
public static void main(String[] args) {//plus you dont need To throw exception thus your program dont throw any!:)
List l = AUtils.generateList();
// List l = AUtils.generateListWithInitialSize(10);//will give you array list with initial size 10
l.add(AUtils.generateAnObject());//if you do so be aware that the objects would be created with 0 as id and eight.
// l.add(AUtils.generateWithData(3,3));
}
}
please be aware that this normally is not acceptable and considered as bad coding because its kinda turn around ;) so either you misunderstood the assignment or the one who wrote it is really a carrot.
happy coding.
You cannot do it directly without changing of the design or visibility of the classes.
If a class has no modifier (the default, also known as
package-private), it is visible only within its own package.
https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

Declaring a nested class in Java

I'm a bit confused with subclasses.
Here's my code:
public class MedHistory {
private String grafts;
private String allergies;
private String diseases;
private String surgeries;
private String medicalTreatment;
//Constructors (#2)
public MedHistory(String allergies, String diseases, String grafts,
String treatments, String surgeries) {
this.allergies=allergies;
this.diseases=diseases;
this.grafts=grafts;
this.medicalTreatment=treatments;
this.surgeries=surgeries;
}
public MedHistory() {
this.allergies="";
this.diseases="";
this.grafts="";
this.medicalTreatment="";
this.surgeries="";
}
//Getters
public String getGrafts() {
return grafts;
}
public String getAllergies() {
return allergies;
}
public String getDiseases() {
return diseases;
}
public String getSurgeries() {
return surgeries;
}
public String getMedicalTreatment() {
return medicalTreatment;
}
//Setters
public void setGrafts(String grafts) {
this.grafts = grafts;
}
public void setAllergies(String allergies) {
this.allergies = allergies;
}
public void setDiseases(String diseases) {
this.diseases = diseases;
}
public void setSurgeries(String surgeries) {
this.surgeries = surgeries;
}
public void setMedicalTreatment(String medicalTreatment) {
this.medicalTreatment = medicalTreatment;
}
public class FemMedHistory extends MedHistory {
private List<Birth> births = new ArrayList<Birth>();
//Constructors (#2)
public FemMedHistory(String allergies, String diseases, String grafts,String treatments, String surgeries, List<Birth> birthlist) {
super(allergies,allergies,grafts,treatments,surgeries);
this.births=birthlist;
}
public FemMedHistory() {
super();
this.births=null;
}
//Getter
public List<Birth> getBirths() {
return this.births;
}
//Setter
public void setBirths(List<Birth> list) {
this.births=list;
}
}
}
When I try to create an new FemMedHistory object like this:
List<Birth> list = new ArrayList<Birth>();
list.add(new Birth(new GregorianCalendar(2011,4,10),"kaisariki",4));
FemMedHistory female = new FemMedHistory("allergia2","astheneia2","emvolia2","farmekeutiki agwgi2", "xeirourgeia2", list);
I get the error:
No enclosing instance of type MedHistory is accessible. Must qualify
the allocation with an enclosing instance of type MedHistory (e.g.
x.new A() where x is an instance of MedHistory).
So, which is the right way to use a subclass?
When you declare a nested class it only available through the Outer class.
To access it outside, you will need to either make the FemMedHistory class static.
public static class FemMedHistory extends MedHistory {...}
access it through the MedHistory class
MedHistory.FemMedHistory myMedHistory = ...
or declare it in it's own Java file.
You have declared your subclass as an inner class, which means that you can't create an instance of it without first creating an instance of the containing class.
The most common way to solve this is to declare it as a separate class, which would get rid of your error.
Long story short: cut all the FemMedHistory code and paste it into FemMedHistory.java. The way it is now you have involved Java concepts which you have not yet mastered. Also, that class really does belong in a separate file.

How can I add a protected method to a class implementing an interface in java?

I have a class called Property which has nothing but get-methods. All the fields will be set when a new instance of Propertyis created. Property implements an interface called IProperty.
Due to some bug in a library I use, I have to set the name of an instance of Property anew after its creation. Therefore it was suggested to create a WrapperPropertyclass that will provide a public setName-method which itself calls a therefore created setName()-method in Property, which will be protected/package view.
The problem is that I cannot make this method protected in Property, because Eclipse tells me to add it to the interface IProperty and make it public.
Is there some work-around to it?
WrapperIProperty:
public class WrapperIProperty {
private IProperty prop;
WrapperIProperty(Property prop) {
this.prop = prop;
}
public void setName(String name) {
prop.setName(name);
}
}
Property:
public class Property implements IProperty {
String name;
protected void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public int getFoobar() {
return 123;
}
public int getWhatever() {
return 987;
}
}
IProperty:
public interface IProperty {
public int getWhatever();
public int getFoobar();
public String getName();
}
This is how it looks at the moment. Obviously it won't work, since I cannot let the method be protected in the Property class. Therefore I best get rid of the interfacee entry somehow. But how?
What you probably want to do is to leave the IProperty interface alone (don't add the setName method to it) and create a delegating wrapper class which provides the method you want (wraps an implementation of the interface).
This way you can feed wrapped properties and regular properties to whatever needs them.
public class WrappedProperty implements IProperty {
private String name;
private Property prop;
WrappedProperty (Property prop) {
this.prop = prop;
}
protected void setName(String name) {
this.name = name;
}
public int getWhatever() {
return prop.getWhatever();
}
public int getFoobar() {
return prop.getFoobar();
}
public String getName() {
if (this.name == null) {
return prop.getName():
} else {
return this.name;
}
}
}
public class Property implements IProperty {
public String getName() {
return "blah";
}
public int getFoobar() {
return 123;
}
public int getWhatever() {
return 987;
}
}
public interface IProperty {
public int getWhatever();
public int getFoobar();
public String getName();
}
Methods in an Interface are public in scope so implementing class cannot override methods by reducing their accessibility. Make them public
You cannot have a public methodName in an Interface and a private or protected methodName in a Class implementing this Interface.
So you can have the methodName public in your Class :
this method do nothing
this method call [another]methodNameProtected (you give another name to a new protected method)
UPDATE
If you want it only in Interface you have to change your Interface in an AbstractClass and put in it the method
public final returnCode methodName if the method is common for all inherited classes
Found the solution to that problem:
WrapperIProperty :
public class WrapperIProperty {
private Property prop;
public WrapperIProperty(IProperty prop) {
this.prop = (Property) prop;
}
public void setName(String name) {
prop.setName(name);
}
}
Property:
public class Property implements IProperty {
private String name = null;
[...]
void setName(String name) {
this.name = name;
}
}
IProperty:
public interface IProperty {
[...]
}
This will do the job

Selecting correct Enum

I have a number of Enums each of which contain the names of attributes to be tested. The problem I have is how to select the relevant enum for the object. How can I define just a Enum variable which use throughout my code which can be set through an initalise method.
EDIT:
Sorry for the delayed reponse. I had to step away from the desk
It very well be bad design. I have a few enums as follows:
public enum AccountGrpEnum {
Account("Account"),
AccountType("AccountType"),
AcctIDSource("AcctIDSource");
private static Set<String> grpNames = new HashSet<String>(3) {{
for(AccountGrpEnum e : AccountGrpEnum.values()) {
add(e.toString());
}
}};
public static boolean contains(String name) {
return grpNames.contains(name);
}
private String name;
private AccountGrpEnum(String name) {
this.name = name;
}
public String toString() {
return this.name;
}
}
Another Enum:
public enum BlockManValEnum {
avgPx("avgPx"),
quantity("quantity"),
securityIDSource("securityIDSource"),
securityID("securityID"),
blockStatus("blockStatus"),
side("side");
private static Set<String> names = new HashSet<String>(9) {{
for(BlockManValEnum e : BlockManValEnum.values()) {
add(e.toString());
}
}};
public static boolean contains(String name) {
return names.contains(name);
}
private String name;
private BlockManValEnum(String name) {
this.name = name;
}
public String toString() {
return this.name;
}
}
Within my code I am checking the fields of an incoming object to see they are contained within the Enum. As follows:
if (BlockManValEnum.contains(fields[i].getName()))
however I would like it to be along the lines of
if (variableEnum.contains(fields[i].getName()))
Where variableEnum can be set at runtime.
Hope this is clearer guys
Building on previous answers.
enum Color {
RED(1),
GREEN(2),
BLUE(3);
int attrib;
Color(int attribValue) {
attrib = attribValue;
}
public Color getColorForAttrib(int attribValue) {
for(Color c : Color.values()) {
if(c.attrib == attribValue) {
return c;
}
}
throw new IllegalArgumentException("No color could be found for attrib of value " + attribValue);
}
}
...
class SomeClass {
Color c;
public void SomeClass(Color c) {
this.c = c;
}
}
...
class SomeClassUser {
public static void main(String[] args) {
Color c = Color.getColorForAttrib(Integer.valueOf(args[i]));
new SomeClass(c);
}
}
Remember that simplistically, enums are just a class, so you can add any methods you want to them. Whether or not it's a good idea depends on circumstance
Use Enum.valueOf:
Enum<?> variableEnum = AccountGrpEnum.class;
if(Enum.valueOf(variableEnum.getClass(), field[i].getName()) != null) {
doSomething();
}
Since enums are classes and thus can implement interfaces, you could create an interface which holds your contains() method and then implement that method on your enums, then use a generic method which takes a class token of a specific enum type implementing that interface (and which could be set at runtime) to test. Something like this:
CanBeTestedForContains:
public interface CanBeTestedForContains {
boolean contains(String name);
}
ColorEnum:
import java.util.HashSet;
import java.util.Set;
public enum ColorEnum implements CanBeTestedForContains {
R("red"),
B("blue");
private static Set<String> names = new HashSet<String>(3) {
{
for (final ColorEnum e : ColorEnum.values()) {
add(e.name);
}
}
};
private String name;
private ColorEnum(final String name) {
this.name = name;
}
#Override
public boolean contains(final String name) {
return names.contains(name);
}
}
SuitEnum:
import java.util.HashSet;
import java.util.Set;
public enum SuitEnum implements CanBeTestedForContains {
D("diamonds"),
H("hearts"),
C("clubs"),
S("spades");
private static Set<String> names = new HashSet<String>(3) {
{
for (final SuitEnum e : SuitEnum.values()) {
add(e.name);
}
}
};
private String name;
private SuitEnum(final String name) {
this.name = name;
}
#Override
public boolean contains(final String name) {
return names.contains(name);
}
}
ContainsSelectorTest:
public class ContainsSelectorTest {
private static <E extends Enum<E> & CanBeTestedForContains> boolean contains(final Class<E> enumClass, final String name) {
return enumClass.getEnumConstants()[0].contains(name);
}
public static void main(final String[] args) {
if (contains(ColorEnum.class, "red")) {
System.out.printf("%s contains %s\n", ColorEnum.class, "red");
}
if (contains(SuitEnum.class, "hearts")) {
System.out.printf("%s contains %s\n", SuitEnum.class, "hearts");
}
if (contains(SuitEnum.class, "red")) {
System.out.println("This shouldn't happen.");
} else {
System.out.printf("%s DOES NOT contain %s\n", SuitEnum.class, "red");
}
}
}
Output:
class ColorEnum contains red
class SuitEnum contains hearts class
class SuitEnum DOES NOT contain red

Factory class design issue in java

I have two classes
public class PrepaidPackage {
private String name;
private String serviceClassID;
private boolean isTranferable;
public boolean isTranferable() {
return isTranferable;
}
public void setTranferable(boolean isTranferable) {
this.isTranferable = isTranferable;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getServiceClassID() {
return serviceClassID;
}
public void setServiceClassID(String serviceClassID) {
this.serviceClassID = serviceClassID;
}
}
other class is
public class PostpaidPackage {
private String name;
private boolean isTranferable;
public boolean isTranferable() {
return isTranferable;
}
public void setTranferable(boolean isTranferable) {
this.isTranferable = isTranferable;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I want to create a factory class which on base of package type create relevant class. But if you look at above clasess they dont have same type of methods and variables. So please guide how create interface or abstract class for above class?
Now factory will return class name Package. Would i able to call methods which are not present in other class.
Updates
Please suggest if i break my package into two classes like
public abstract class MyPackage {
public abstract PackageSpec getSpec();
public abstract PackagePrepaidDetails getDetail();
}
Now common attributes will be in PackageSpec and prepaid stuff in packageDetails.
Its kind of abstract factory pattern.
public class PrepaidPackage extends MyPackage{
PackageSpec spec;
public Spec getSpec() {
spec = new PackageSpec();
spec.setTranferable(true)
spec.setName("abc");
return spec;
}
public PackagePrepaidDetails getDetails() {
details = new PackagePrepaidDetails ();
details.setServiceClassID(123)
return details;
}
}
public class PostpaidPackage extends MyPackage{
PackageSpec spec;
public Spec getSpec() {
spec = new PackageSpec();
spec.setTranferable(true)
spec.setName("abc");
return spec;
}
}
I recomment you to have an interface if you don't have already. You do not neccessarily need it, but it is a good practice if they are so similar:
public interface Package {
public boolean isTranferable();
public void setTranferable(boolean isTranferable);
public String getName();
public void setName(String name);
}
Then in your calling code, you have a Package from your factory and:
Package p = myFactory.nextPackage(); // or something
if (p instanceof PrepaidPackage) {
PrepaidPackage prepaid = (PrefpaidPackage)p;
// and do the thing you want
} else if (p instanceof PostpaidPackage) {
PostpaidPackage postpaid = (PostpaidPackage)p;
// amd do the other things
}
Thing you are recommended to llok into is the instanceof operator and type casting.
A quick fix, not an ideal one is to have an interface that represents all the methods in the Prepaid class and leave them unimplemented in the Postpaid. That will solve the problem in the short term. I would suggest that you have a relook of the classes and the usages to avoid unimplemented methods in the code.
Well for an abstract super class you have to group everything common to both :
public abstract class MyPackage { // not sure you can call a class just "Package"
private String name;
private boolean isTranferable;
public boolean isTranferable() {
return isTranferable;
}
public void setTranferable(boolean isTranferable) {
this.isTranferable = isTranferable;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
then both inherits from it (the first adds serviceClassID and the second nothing)
your factory function will return a MyPackage (or AbstractPackage, whatever), but to access the specific function you'll have to cast after an instanceof test.
Two possible design choices you can make:
Have the prepaid package extend
postpaid package and your factory
then returns objects of type
postpaid package, the code which
calls the factory is then
responsible for inspecting the type.
Have a package interface which
defines all of the methods and have
postpaid package define the methods
to throw an
UnsupportedOperationException (ala
the way collections defines some
operations as optional.) or return
some kind of sentinel value (i.e. null)
For either of the above you could add another method getType() which returns an enum of the various package types you wish to implement, and this could then be used in the code that accesses the factory objects to determine which methods are available.

Categories

Resources