Injecting annotation values from ResourceBundle - json

How can I read a value for an annotation from a ResourceBundle?
Instead of using a fixed value for #JsonProperty("myPropertyName") I wonder if it is possible to do something like #JsonProperty(env.getProperty("json.property.myproperty")).

No, it is not possible. The java language specification states
It is a compile-time error if the return type of a method declared in
an annotation type is not one of the following: a primitive type,
String, Class, any parameterized invocation of Class, an enum type
(§8.9), an annotation type, or an array type (§10) whose element type
is one of the preceding types.
Spring processes your beans at runtime. The annotation needs to have its attribute values at compile time.

Related

Typescript: undefined calculated property after deserializing in JSON

I'm new to Typescript and I encountered a JSON deserializing problem.
Consider this class:
class Product {
public id!: number;
public get calculatedProperty() : string {
return "Test";
};
};
As you can see calculatedProperty is a runtime calculated property.
Also, consider that I deserialize a JSON string into my object in this way:
var jsonData = '{ "id": 2 }';
let deserialized = JSON.parse(jsonData) as Product;
The problem comes now:
This call console.log(deserialized.id); returns correctly 1.
This call console.log(deserialized.calculatedProperty); returns undefined!
I really don't understand way. It seems that as Product doesn't really create a Product object, because If I directly invoke the constructor, new Product, the calculated property exists.
What am I doing wrong with the JSON deserialization?
Thanks!
TypeScript's job is only to perform type checking during development and make sure we don't make careless mistakes. At the end of the day, all it does is just compiling the script and transform it into good old JavaScript. Therefore, any TypeScript syntax are not applied in runtime.
In other words, type assertions are removed in runtime.
There are also several warnings in the documentation about this:
Like a type annotation, type assertions are removed by the compiler and won’t affect the runtime behavior of your code.
Reminder: Because type assertions are removed at compile-time, there is no runtime checking associated with a type assertion. There won’t be an exception or null generated if the type assertion is wrong.
Besides, the as keyword does not instantiate a constructor. It merely provides a type information (which will be removed during compile-time). The only way we can instantiate a constructor and access its instance properties/methods is through the new keyword.
The JSON.parse method isn't really for converting json into a class rather than an object.
To solve your issue you could potentially convert the json into an object like this:
let deserializedObject = JSON.parse(jsonData) as Object;
and after that you could assign the object to a class like that:
let deserialized = Object.assign(new Product(), deserializedObject);
Note that I have not tested this yet, but it should work.
Also this is fine for simple objects, but not for objects with complex hierarchy.
Look into class-transformer for more information. https://github.com/typestack/class-transformer

Storing json, jsonb, hstore, xml, enum, ipaddr, etc fails with "column "x" is of type json but expression is of type character varying"

When using PostgreSQL to store data in a field of a string-like validated type, like xml, json, jsonb, xml, ltree, etc, the INSERT or UPDATE fails with an error like:
column "the_col" is of type json but expression is of type character varying
... or
column "the_col" is of type json but expression is of type text
Why? What can I do about it?
I'm using JDBC (PgJDBC).
This happens via Hibernate, JPA, and all sorts of other abstraction layers.
The "standard" advice from the PostgreSQL team is to use a CAST in the SQL. This is not useful for people using query generators or ORMs, especially if those systems don't have explicit support for database types like json, so they're mapped via String in the application.
Some ORMs permit the implementation of custom type handlers, but I don't really want to write a custom handler for each data type for each ORM, e.g. json on Hibernate, json on EclipseLink, json on OpenJPA, xml on Hibernate, ... etc. There's no JPA2 SPI for writing a generic custom type handler. I'm looking for a general solution.
Why it happens
The problem is that PostgreSQL is overly strict about casts between text and non-text data types. It will not allow an implicit cast (one without a CAST or :: in the SQL) from a text type like text or varchar (character varying) to a text-like non-text type like json, xml, etc.
The PgJDBC driver specifies the data type of varchar when you call setString to assign a parameter. If the database type of the column, function argument, etc, is not actually varchar or text, but instead another type, you get a type error. This is also true of quite a lot of other drivers and ORMs.
PgJDBC: stringtype=unspecified
The best option when using PgJDBC is generally to pass the parameter stringtype=unspecified. This overrides the default behaviour of passing setString values as varchar and instead leaves it up to the database to "guess" their data type. In almost all cases this does exactly what you want, passing the string to the input validator for the type you want to store.
All: CREATE CAST ... WITH FUNCTION ...
You can instead CREATE CAST to define a data-type specific cast to permit this on a type-by-type basis, but this can have side effects elsewhere. If you do this, do not use WITHOUT FUNCTION casts, they will bypass type validation and result in errors. You must use the input/validation function for the data type. Using CREATE CAST is suitable for users of other database drivers that don't have any way to stop the driver specifying the type for string/text parameters.
e.g.
CREATE OR REPLACE FUNCTION json_intext(text) RETURNS json AS $$
SELECT json_in($1::cstring);
$$ LANGUAGE SQL IMMUTABLE;
CREATE CAST (text AS json)
WITH FUNCTION json_intext(text) AS IMPLICIT;
All: Custom type handler
If your ORM permits, you can implement a custom type handler for the data type and that specific ORM. This mostly useful when you're using native Java type that maps well to the PostgreSQL type, rather than using String, though it can also work if your ORM lets you specify type handlers using annotations etc.
Methods for implementing custom type handlers are driver-, language- and ORM-specific. Here's an example for Java and Hibernate for json.
PgJDBC: type handler using PGObject
If you're using a native Java type in Java, you can extend PGObject to provide a PgJDBC type mapping for your type. You will probably also need to implement an ORM-specific type handler to use your PGObject, since most ORMs will just call toString on types they don't recognise. This is the preferred way to map complex types between Java and PostgreSQL, but also the most complex.
PgJDBC: Type handler using setObject(int, Object)
If you're using String to hold the value in Java, rather than a more specific type, you can invoke the JDBC method setObject(integer, Object) to store the string with no particular data type specified. The JDBC driver will send the string representation, and the database will infer the type from the destination column type or function argument type.
See also
Questions:
Mapping postgreSQL JSON column to Hibernate value type
Are JPA (EclipseLink) custom types possible?
External:
http://www.postgresql.org/message-id/54096082.1090009#2ndquadrant.com
https://github.com/pgjdbc/pgjdbc/issues/265
http://www.pateldenish.com/2013/05/inserting-json-data-into-postgres-using-jdbc-driver.html

one Jackson deserializer for multiple types (config by annotation)

I'm trying to change the (de)serialization of a list in one of my classes.
the objects in the list shall be serialised as int (their jpa id) and deserialised accordingly. serialization is simple.
for the deserialization i have a class that can translate the id into the object if id and class are known.
How do i get the necessary class from jackson? all default jackson serialisers have a constructor like this: protected StdDeserialiser(Class<?> vc) so the information is present somewhere.
is there a way to access it during deserialisation?
or before the deserialiser is constructed by jackson?
or inside the HandlerInstantiator?
I only want to overwrite the default deseriliser for certain references so i can't just write a provider or a custom module.
I made it work from inside the deserializer with the help of the ContextDeserializer interface as this supplies the deserializer with the target property.
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException {
Class<?> vc = null;
if (property.getType().isCollectionLikeType()) {
vc = property.getType().getContentType().getRawClass();
} else {
vc = property.getType().getRawClass();
}
return new ResourcePathDeserializer(vc, converter);
}
This solution is not perfect as I only get the raw class of the return type or the generic (which might be a parent class or an interface) but that is enough for my requirements.
It would be better if I could access the "real" class that was resolved by Jackson, but for me this works.
First of all, there is nothing fancy about writing a Module: it is just a way for plugging things in, like custom (de)serializers. So no need to avoid that. And you will most like need to write a module to do what you want.
In general it is not a good idea to try to create "universal" serializers or deserializers, and it will probably run into problem. But it depends on what exactly you are trying to do.
Type information will either be:
Implicit from context: you are writing a (de)serializer for type T, and register it for it, so that's your type
Passed by Jackson when (de)serializer is being constructed, via Module interface: modules are asked if they happen to have a (de)serializer for type T. SimpleModule will only use basic Class-to-impl mapping (that's where "simple" comes from); but full custom Module has access to incoming type.
But I don't know if above will work for your use case. Type information must be available from static type (declared content type for the list).

How to serialize transient fields in the model via FlexJson?

I am using Play Framework to expose REST API, which returns some JSON objects.
To simplify the API usage, I would like to return a "calculated" field in the response.
Unfortunately, in my tests, while FlexJson does not ignore the transient model fields completely, but always sets them to 'null'.
More details:
In the model class, I define:
#Transient
public String currencyName;
The only constructor of the class set the value to "dollar" (for debugging purposes):
this.currencyName = "dollar";
When serializing the class using FlexJson, when the 'currencyName' field is not specified in the include/ exclude - the result always looks like:
"currencyName":null
Any idea what got wrong, and how to get the field value serialized into JSON?
Thanks in advance.
By definition if your field is transient it will not be serialized. Perhaps this field should not be transient in your application if the state matters.

Parsing JSON objects of unknown type with AutoBean on GWT

My server returns a list of objects in JSON. They might be Cats or Dogs, for example.
When I know that they'll all be Cats, I can set the AutoBeanCodex to work easily. When I don't know what types they are, though... what should I do?
I could give all of my entities a type field, but then I'd have to parse each entity before passing it to the AutoBeanCodex, which borders on defeating the point. What other options do I have?
Just got to play with this the other day, and fought it for a few hours, trying #Category methods and others, until I found this: You can create a property of type Splittable, which represents the underlying transport type that has some encoding for booleans/Strings/Lists/Maps. In my case, I know some enveloping type that goes over the wire at design time, and based on some other property, some other field can be any number of other autobeans.
You don't even need to know the type of the other bean at compile time, you could get values out using Splittable's methods, but if using autobeans anyway, it is nice to define the data that is wrapped.
interface Envelope {
String getStatus();
String getDataType();
Splittable getData();
}
(Setters might be desired if you sending data as well as recieving - encoding a bean into a `Splittable to send it in an envelope is even easier than decoding it)
The JSON sent over the wire is decoded (probably using AutoBeanCodex) into the Envelope type, and after you've decided what type must be coming out of the getData() method, call something like this to get the nested object out
SpecificNestedBean bean = AutoBeanCodex.decode(factory,
SpecificNestedBean.class,
env.getData()).as();
The Envelope type and the nested types (in factory above) don't even need to be the same AutoBeanFactory type. This could allow you to abstract out the reading/writing of envelopes from the generic transport instance, and use a specific factory for each dataType string property to decode the data's model (and nested models).