I have a class Parent
public class Parent
{
private int id;
#JsonIgnore
int getId() {}
void setId(int id) {}
}
I have a subclass which is derived from Parent
public class Child extends Parent
{
#JsonProperty // just to explicitly tell jackson to serialize this
#Override
int getId() {}
#Override
void setId(int id) {}
}
I actually don't want the id property to be serialized when an object of Parent is returned but it should be serialized when an object of Child class is returned.
I think if Parent was an Interface, overriding the visibility would work, but I am not sure if the behavior is the same with superclass.
Is there a simple solution for this? I would really appreciate your answers. Tx.
What you want in the Child class is not #JsonProperty but instead #JsonIgnore(false).
Related
I am using JDK 7.
I have an abstract class BaseEntity which is using generics:
public class BaseEntity<Id extends java.io.Serializable> {
protected Id id;
public BaseEntity() {
}
public Id getId() {
return id;
}
public void setId(Id id) {
this.id = id;
}
// also has hashCode() and equals() methods to be based on id
}
Now I want to create an interface whose type would be BaseEntity and I also want the Id of BaseEntity to be available in the interface. How can I do that?
I tried this code:
public interface BaseLookup<T extends BaseEntity> {
T findById(Id id);
}
but I got 2 messages:
1st one was on BaseEntity. The message was:
Base Entity is a raw type. References to generic type BaseEntity<Id>
should be parameterized.
2nd one was on "Id". The error message was:
Id cannot be resolved to a type.
What I am doing wrong here?
You have to specify the type of BaseEntity in BaseLookup. For better readability, I defind ID type as I.
You could use something like this:
class BaseEntity<I extends java.io.Serializable> {
protected I id;
public BaseEntity() {
}
public I getId() {
return id;
}
public void setId(I id) {
this.id = id;
}
// also has hashCode() and equals() methods to be based on id
}
interface BaseLookup<I extends java.io.Serializable, T extends BaseEntity<I>> {
T findById(I id);
}
public interface BaseLookup<Id, T extends BaseEntity<Id>> {
T findById(Id id);
}
Since you parameterized BaseEntity, you should always use a parameter whenever you reference BaseEntity. That first warning you got was telling you that you were using the BaseEntity (with no parameters) raw type, which is something that really only exists for legacy code and shouldn't be used. Since, ostensibly, BaseEntity is not just one type but an entire collection of types (one for each T), we need to tell it which BaseEntity we're extending, which amounts to adding an additional generic argument.
I have two classes that implements from two interfaces.
Here is my interfaces:
interface Identifiable {
int getId();
}
interface Greetable {
String helloMessage();
String byeMessage();
}
Here is my classes:
public class Lecturer implements Greetable, Identifiable {
private int employeeId;
private String name;
private String title;
#Override
public String helloMessage() {
return name;
}
#Override
public String byeMessage() {
return title;
}
}
public class Student implements Greetable, Identifiable {
private char examScore;
#Override
public String helloMessage() {
return "Hi";
}
#Override
public String byeMessage() {
return "Whats up";
}
}
I get the error from the classes that it has to abstract the methods from the interfaces? What does that mean?
Non-abstract classes are required to create concrete versions of any methods found in any interfaces that they're implementing, and while your classes implement concrete versions of one of the interface, the Greetable interface, you're not implementing all the methods of both interfaces, here the public int getId() method from the Identifiable interface is missing from both classes.
Solution: give both classes an int id field as well as the getId() method that returns the value held by this field.
e.g. for Student,
public class Student implements Greetable, Identifiable {
private char examScore;
private int id; // **** your classes will need this field ****
// need to set the ID somehow, either with a setter or a constructor
public Student(int id) {
this.id = id;
}
#Override
public String helloMessage() {
return "Hi";
}
#Override
public String byeMessage() {
return "Whats up";
}
#Override // **************** add this method to return the value held by id ******
public int getId() {
return this.id;
}
}
You define to implement both interfaces, but you only implemented the methods of the second interface.
So you have to implement the method getId() in both classes.
You havent implemeted the getId() method in Identifiable. If you are not implementing that method you need to make the Lecturer and Student as abstract or you need to implement the getId() method in both the classes.
In your case I think you will need to create instances of the Student and Lecturer. If so then you cannot make them as abstract, as abstract class instances cannot be created. So better implement the getId() in both the classes.
Your Student and Lecturer classes MUST implement both Greetable, Identifiable interface methods, otherwise they need to be declared as abstract classes i.e., you are missing getId() from Identifiable interface, which is causing the issues, corrected code below.
Lecturer class:
public class Lecturer implements Greetable, Identifiable {
int getId() {
return employeeId;
}
//all other existing methods
}
Student class:
public class Student implements Greetable, Identifiable {
int getId() {
return studentId;
}
//all other existing methods
}
You can look here
I would like all my objects to have an ID and I wish to serialise it for some child class but not for some others
for example:
public class A {
protected Long id;
..getter and setter
}
public class B extends A {
#Override
#JsonIgnore
public Long getId() {..}
#Override
#JsonIgnore
public void setId(Long id) {..}
}
public class C extends B {
#Override
#JsonInclude
public Long getId() {..}
#Override
#JsonInclude
public void setId(Long id) {..}
}
public class Test {
Set<C> tests ...
..getter setter
}
I have tried serialising Test but the JSON string doesn't include the IDs
If I remove the JsonIgnore from B then in that case the Ids are there.
Is there a way with jackson to archive this?
Use
#JsonIgnore(false)
instead of
#JsonInclude
I have implemented a REST API with SPRING REST using Jackson (specifying in the pom.xml with the package org.codehaus.jackson - jackson-mapper-asl - 1.9.13). In the controller I have:
#Controller
#RequestMapping("/test")
public class TestController {
#RequestMapping(value="id", method= RequestMethod.GET)
#ResponseBody
public Parent findById(#PathVariable("id") int id) {
Child child = new Child();
child.setId(id);
child.setName("test");
return child;
}
}
For example in the Parent we could have:
public class Parent {
int id;
public void setId(int id) {
this.id = id;
}
}
And the child:
public class Child extend Parent {
String name;
public void setName(String name) {
this.name = name;
}
}
My problem is that I'd want the response to be only with the parent class and not with the child class (because now the response has the structure of the child).
One solution that would work for you is the following:
#JsonAutoDetect(getterVisibility = JsonAutoDetect.Visibility.NONE)
public class Parent {
#JsonProperty
int id;
public void setId(int id) {
this.id = id;
}
}
I have to admit that this solution is not terribly elegant since you need to add the #JsonProperty annotation to every field in the Parent class, but does have the benefit that no modifications are needed to any of it's subclasses
All the annotations that are present in the jackson library can be found here.
The javadoc for #JsonAutoDetectcan be found here
i've a base class that provide only identification:
public abstract class Identifable<T> {
#Id
private T id = null;
public T getId() {
return id;
}
public void setId(T id) {
this.id = id;
}
public boolean hasId() {
return id != null;
}
}
and several subclasses that extends it like:
#Entity
#Cache
public class MyEntity extends Identifable<String> {
/* some specific attributes and methods */
}
I get an java.lang.IllegalStateException: #Id field 'id' in com.mypkg.MyEntity must be of type Long, long, or String.
Why? Can't Objectify see the inherited #Id field?
Thanks
The cause:
Objectify only inspects types at runtime using reflection. Because of type erasure all unbounded type parameters are during compilation converted to Object type, which is what objectify sees and complains.
The solution:
Use concrete type for id field. Possibly move it to a child class, as proposed by #Anthony.
In JPA, you must use for a field marked with #Id one of the following types:
any Java primitive type; any primitive wrapper type; java.lang.String; java.util.Date; java.sql.Date; java.math.BigDecimal; java.math.BigInteger
Just remove the generics from the base class and use one of the mentioned types for your id field.
Let's reason about if for a while... You are trying to build a super type in which the type of the ID varies. Are you sure that this is what you want objectify to build (a hierarchy of objects in which the root entity has a unknown ID type)? While I've seen this kind of code in several ORM frameworks, this is how I would build what you want.
Interface (not part of the object hierarchy):
public interface Identifable<T> {
public T getId();
public void setId(T id);
public boolean hasId();
}
Root of your hiearchy implements Identifable with a concrete type for the id:
#Entity
public class MyBaseClass implements Identifable<String> {
#Id
private String id = null;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public boolean hasId() {
return id != null;
}
}
And subclass comes naturally out of it:
#EntitySubclass(index=true)
public class MyEntity extends MyBaseClass {
// fields, accessors and mutators
}