Jackson jsonproperty name when there are multiple instances of the same object - java

Take this example:
class Car {
Door leftDoor;
Door rightDoor;
Door getLeftDoor();
Door getRightDoor();
}
class Door {
String getType();
}
The goal is to have this json:
{
"Door.lefttype": "A",
"Door.righttype": "B"
}
I have the object mapper configured that only things with #JsonProperty are converted to Json.
If I only had one door, I could simply put #JsonProperty("door.type") on String getDoorType(). But since there are multiple instances of the same type I can't put the annotation on the last class. Furthermore, I need #JsonUnwrapped because I don't want it to make a hierarchy in the json. I want this:
door.lefttype: "A"
instead of
door: {
lefttype: "A"
}
What I have so far (I'm using interfaces + mixins since I don't have access to the classes directly):
public interface CarMixin {
#JsonProperty
#JsonUnwrapped
Door getLeftDoor();
#JsonProperty
#JsonUnwrapped
Door getRightDoor();
}
public interface DoorMixIn {
#JsonProperty
String getType();
}
I need the exact names, so this doesn't suffice. I need to use named JsonProperties

I don't think I have the same understanding of mixin as you do, and I must say I'm little unclear what is the extend of your limitation in modifying existing classes, but I would think something along the following lines might help:
class Car {
Door leftDoor ;
Door rightDoor ;
#JsonProperty("Door.lefttype")
String leftType() {
return leftDoor.getType() ;
}
#JsonProperty("Door.righttype")
String leftType() {
return rightDoor.getType() ;
}
}

Related

How to create beans dynamically using a DI framework

requirement is like this: user input is single character followed by an array of integers, such as 'A 1 2', 'B 3 4 5', 'C 1', etc. The single character means which class to construct and integers are input parameter to that constructor. Please note different classes might need different number of integers.
Then we need to write a program to parse user input and create objects accordingly.
My approach was to use regular expression for parsing and hard code which class to call.
But another senior developer said a better idea would be using dependency injection to automatically create objects based on user input. He gave another hint to create an interface and use spring framework dependency injection (not spring boot).
I am still confused how to create beans dynamically in this way. Can anybody help please?
You can create a common interface for the classes that can be created, and a Factory bean that transforms the input.
// common interface
interface MyObject {
void someMethod();
}
class A implements MyObject {
public A(List<Integer> params) { ... }
}
class B implements MyObject {
public B(List<Integer> params) { ... }
}
// parsed data
class Input {
char character;
List<Integer> ints;
// getters, setters
}
interface MyObjectFactory {
public MyObject apply(Input input);
}
#Bean
class MyObjectFactory implements MyObjectFactory {
public MyObject apply(Input input) {
// create object from input, eg switch over input.getCharacter()
};
}
// injected
class MyClientService {
#Autowired
MyObjectFactory objectFactory;
public void doStuff() {
List<Input> parsedInputs = parse(something);
for (Input input : parsedInputs) {
MyObject object = objectFactory.apply(input);
// ...
}
}
}

Custom setter to be used in MapStruct

I have been looking through the MapStruct documentation without any success.
I am implementing a mapping between my Domain classes and my DTO classes; using MapStruct. In my domain, I do not want to use Setters for my fields because, we know that today Setters are bad (for many reasons, but that's not the topic of my question).
However when I want to convert ItemDto into Item, I got the following message :
Error:(17, 21) java: Property "name" has no write accessor in my.example.Item.
However my class Item has a Business method void changeName(String newName) that I would like to use in my Mapper.
The code of my Mapper is :
#Mapper
public interface MyMapper {
#Mapping(source="nameDto", target = "name")
Item map(ItemDto dto);
}
My question is quite simple : how to specify StructMap to use changeName as write accessor ?
Thanks for your help.
In order to implement something like that you would have to write your own custom AccessorNamingStrategy.
If your domain objects follow the same pattern changeXXX then a simple implementation can look like:
public class CustomAccessorNamingStrategy extends DefaultAccessorNamingStrategy {
#Override
public boolean isSetterMethod(ExecutableElement method) {
String methodName = method.getSimpleName().toString();
return methodName.startsWith( "change" ) && methodName.length() > 6;
}
#Override
public String getPropertyName(ExecutableElement getterOrSetterMethod) {
String methodName = getterOrSetterMethod.getSimpleName().toString();
if ( methodName.startsWith( "change") {
return IntrospectorUtils.decapitalize( methodName.substring( 6 );
}
return super.getPropertyName( getterOrSetterMethod );
}
}
You can of course adapt the CustomAccessorNamingStrategy to fit your needs. Keep in mind that this would be used for all objects. Also the ItemDto.
More information about it can be found here in the MapStruct documentation.

Chaining Enumerations for hierarchical naming structures?

Since I have a terrible memory, I like to put all the detnd I ails of data objects into enumerations, so I can use code completion in the IDE adon't have to keep referring back to get the name of a table or the name of a field. Usually I use some type of class containing only Enums for the purpose.
Lets say I have table of "Domains" (database source) "Tables" and "Fields" that look something like this:
public class DataObjectNames {
public enum Domains {
Domain1,
Domain2;
}
public enum Domain1Tables {
Customers,
Orders;
}
public enum Domain2Tables {
OrderItems,
Shipments;
}
public enum CustomerFields {
id,
email;
}
public enum OrderFields {
id,
customerId;
}
//fields for OrderItems and Shipments . . .
}
But suppose I wanted to be able to do something like:
Domain1.tables().Customers.fields(). //code completion supplies choices?
What I would like ot happen after I type the period is for autocomplete to provide a choice between .id and .email, much the same as it would if "fields" returned an object with two methods, or if I just typed
CustomerFields.
in the IDE.
In order for that to happen, it seems to me I somehow need to return not a specific instance of an enumeration, but the enumeration itself. I've tried various approaches like this:
public enum Domains {
Domain1 {
#Override
public Enum<?> tables() {
return Domain1Tables.foo();
} //Is there a method that will return the enum itself?
},
Domain2 {
#Override
public Enum<?> tables() {
return Domain2Tables.foo();
};
public abstract Enum<?> tables();
}
But of course I haven't been able to find a funciton foo() that returns the enum class itself.
Any thoughts?
You can't do this with enums because Java's class model doesn't work the way you would need in order for this style to work.
I haven't been able to find a function foo() that returns the enum class itself.
Returning the enum class itself is easy, you just do Domain1Tables.class, but that won't give you the completion you want because what it gives you is a Class<Domain1Tables> object, and that object doesn't have fields named Customers and Orders.
You want to be able to treat the "Domain1Tables" class as if it's an object and refer to the enum constants (which are effectively static final fields) as if they were members of that object, but Java simply doesn't do that.
If you give up on using enums for it, then you can simply have:
public class DataObjectNames {
public class Domains {
class Domain1 {
class Tables {
class Customers {
public static final String id = "id";
public static final String email = "email";
}
}
}
}
}
but in that case DataObjectNames.Domains.Domain1 wouldn't be a valid expression anymore (because it reference to a class scope, but not to an object.
There's probably a solution to what you're trying to do, but without more context I can provide anything more details than what's above.

Gson add field during serialization

I can't find a simple way to add a custom field during serialization in Gson and I was hoping someone else may be able to help.
Here is a sample class to show my issue:
public class A {
String id;
String name;
...
}
When I serialize class A I would like to return something like:
{ "id":"123", "name":"John Doe", "url_to_user":"http://www.example.com/123" }
where url_to_user is not stored in my instance of class A, but can be generated with data in the instance of class A.
Is there a simple way of doing this? I would prefer to avoid writing an entire serializer just to add one field.
Use Gson.toJsonTree to get a JsonElement, with which you can interact dynamically.
A a = getYourAInstanceHere();
Gson gson = new Gson();
JsonElement jsonElement = gson.toJsonTree(a);
jsonElement.getAsJsonObject().addProperty("url_to_user", url);
return gson.toJson(jsonElement);
Well, the top rated answer is quite a quick one and not essentially bad when you are lacking much time but here is the problem: There is no proper separation of concern
You are modifying the serialized JSON at the same place where you are writing your business logic. You should be doing all the serialization inside of a TypeAdapter or a JsonSerializer.
How can we maintain a proper separation of concern?
The answer wraps around a bit of additional complexity but the architecture demands it. Here we go(taken from my other answer):
First, we would be using a custom serializer for the type. Second, we would have to create a copy constructor inside the base class and a wrapper subclass as follows:
Note: The custom serializer might seem like an overkill but trust me, it pays off in long run for maintainability.
.
// Lets say the base class is named Cat
public class Cat {
public String name;
public Cat(String name) {
super();
this.name = name;
}
// COPY CONSTRUCTOR
public Cat(Cat cat) {
this.name = cat.name;
}
#Override
public String sound() {
return name + " : \"meaow\"";
};
}
// The wrapper subclass for serialization
public class CatWrapper extends Cat{
public CatWrapper(String name) {
super(name);
}
public CatWrapper(Cat cat) {
super(cat);
}
}
And the serializer for the type Cat:
public class CatSerializer implements JsonSerializer<Cat> {
#Override
public JsonElement serialize(Cat src, Type typeOfSrc, JsonSerializationContext context) {
// Essentially the same as the type Cat
JsonElement catWrapped = context.serialize(new CatWrapper(src));
// Here, we can customize the generated JSON from the wrapper as we want.
// We can add a field, remove a field, etc.
// The main logic from the top rated answer now here instead of *spilling* around(Kindly ignore the cat having a url for the sake of example)
return catWrapped.getAsJsonObject().addProperty("url_to_user", url);
}
}
So, why a copy constructor?
Well, once you define the copy constructor, no matter how much the base class changes, your wrapper will continue with the same role. Secondly, if we don't define a copy constructor and simply subclass the base class then we would have to "talk" in terms of the extended class, i.e, CatWrapper. It is quite possible that your components talk in terms of the base class and not the wrapper type.

Java: force implementor of an interface to have an immutable name field?

Requirement: I'd like all implementations of an interface to have a well-defined name.
Initially, I thought:
interface Fruit {
public String getName();
}
But this allows the user to have a field that is modified at run-time. I want to have an immutable name that is defined before compile/build time.
I've been toying with a couple of other ways to do it, but each has a limitation.
1) Give the name a type, which has slightly more control than free-form strings:
interface Fruit {
public FruitName getName();
}
abstract class FruitName {
public final String NAME;
public FruitName(name) {
this.NAME = name;
}
}
A user of this class will look like this:
class AppleFruitName extends FruitName {
public AppleFruitName() {
super("apple");
}
}
class Apple implements Fruit {
public FruitName getName() {
return new AppleFruitName();
}
}
2) Force an implementor of Fruit to annotate the name with something:
class Apple implements Fruit {
#FruitName
public static final NAME = "apple";
...
}
Clearly this implementation is far cleaner than (1), but I'm not sure if this is possible in Java? How do you get compile/build to fail if #FruitName is not present?
An easy way to do this - without aop, compile time weaving, runtime annotations, scanning at runtime.. etc is to encapsulate this behaviour in an abstract class:
interface Fruit {
public String getName();
}
abstract class FruitImpl {
private final String name;
public FruitImpl(name) {
this.name = name;
}
public final String getFruitName(){
return name;
}
}
So at construction time each implementation will be forced to pass in its name and it will not be able to alter it (unless the user is being intentionally malicious). This meets the what the wording of the question suggests.
There is a difference though because some the suggestions seem to assume that all implementations of the interface will have the same name - though the question doesn't state that. Is the idea that these implementations will be singletons?
Alternatively, you could use the decorator pattern to wrap the implementation and retrieve the field value once and then always return that value later, like this:
class FruitWrapper implements Fruit{
private final String name;
public FruitWrapper(Fruit fruit) {
this.name = fruit.getFruitName();
}
public final String getFruitName(){
return name;
}
}
So you can use it everywhere you would use fruit and it will guarantee to always get the same value.
This way you move the immutability into a class you control.
There are several options to enforce this.
At build time you could write tests for each of the Fruit classes that look for a field that satisfies your requirements.
At build time you could write a single test that goes through your entire classpath and verifies that each Fruit classes satisfies your requirements. A library like Reflections could help you to achieve this.
At compile time you could process an Annotation. I am not sure how you would make sure that each of your classes had an Annotation (as opposed that each class that contains an Annotation is one of the classes in your set.)
At implementation time, as a slight variation on your request, you could use an abstract class instead of an interface and require all implementors to hand you the fixed data in the constructor. That way, you have absolute control over the behaviour.
At runtime, while the application launches, you could check that all implementing classes satify your requirements in the same way an integration test would do it. In a scenario where third parties contribute to your API, this might be the last-stop option if you absolutely have to check it.
I think it is best to use tests for this. You'll have all the certainty you need with far better feedback and much less effort.
If tests are not an option, because you can't control the implementers, I'd go for the abstract class with enforcement during launch as a last resort.
Aren't you confusing static and final?
abstract class FruitName {
private final String name;
public FruitName(String name) {
this.name = name;
}
}
This is the best you can get in terms of interfaces/classes. You can also use custom annotation, but in slightly different way:
#FruitName("apple")
class Apple implements Fruit
And also consider using simple class name:
Fruit fruit = new Apple();
fruit.getClass().getSimpleName(); //"Apple"
But if you depend on class names somewhere, simple refactoring will ruin other parts of the code. So I would consider annotation more stable.
Bonus: your problem is easily solvable in scala:
trait Fruit {
val name: String //abstract AND final
}
class Apple extends Fruit {
val name = "apple" //you MUST implement this
}
If you don't "implement" val name (actually it is an immutable field), compiler will insist on marking Apple abstract.
you should be able to do it with aspectj and compile time waving

Categories