Jackson annotations broken in Scala from 1.9 to 2.1 - java

Just upgraded Jackson from 1.9 to 2.1 and immediately noticed that #(JsonProperty#field) annotations are broken. Note the special #field for Scala case classes. Here's a sample:
case class Watcher(
#(JsonProperty#field)("guid")
#(RiakKey#field)
val guid: String,
#(JsonProperty#field)("socialNetwork")
val socialNetwork: String, // instragram, twitter
)
When I go to pull a Watcher serialized as JSON from the database, Jackson goes to deserialize it and it throws the exception:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "guid" (class com.domain.SocialStreamService.models.Watcher), not marked as ignorable (0 known properties: ])
Now since this was working in 1.9, I am assuming something has changed. Anyone know the cause of the issue? Thanks!

It was caused by a namespace issue and the fact that I was using Jerkson (which still pulled in 1.x as a dependency, thus not throwing compiler errors). To solve the issue, I had to go change the namespaces from com.codehaus to com.fasterxml.
In the meantime, there is a legacy introspector for those who need it: https://github.com/Laures/jackson-legacy-introspector

Related

JsonJackson not adding #class

I am using kotlin with redisson and jsonjackson as the serializer. Previously when I used jackson in java, it would automatically add a '#class' tag to the json so when I came to deserialize it, it would work fine and redisson would know what class to use. Now it no longer does this and when I try to get something out of an RMap<UUID, UserProfile> (UserProfile is an interface", it gives an error which says "jacksonjson missing type id property '#class'" which is obvisouly due to the json missing the '#class' tag.
Anyone know how I can fix this and have jackson automatically add the #class tag like it previously did? Thank you
Fixed this by adding #JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) to the implementation class

Multiple aliases present in json during jackson deserialization

I have a "Request" POJO for my Java API service (Java 11). The POJO is created using Jackson deserialization (jackson databind 2.12.3). One of the POJO's fields has an alias (#JsonAlias) for backward compatibility in the API. How do I instruct jackson to throw an error if both versions of the field are present in the json (actual field name version & aliased version) ?
Here's a small demo app for the above scenario:
// Sample POJO
#lombok.Data
public class A {
#com.fasterxml.jackson.annotation.JsonAlias("y")
private int x; // Field names "x" with alias "y"
}
// Executed code
var om = new ObjectMapper().disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE);
System.out.println(om.readValue("{\"x\": 1}", A.class));
System.out.println(om.readValue("{\"y\": 1}", A.class));
System.out.println(om.readValue("{\"x\": 1, \"y\": 1}", A.class));
System.out.println(om.readValue("{\"x\": 1, \"y\": 2}", A.class));
System.out.println(om.readValue("{\"y\": 1, \"x\": 2}", A.class));
// Output
A(x=1)
A(x=1)
A(x=1)
A(x=2)
A(x=2)
I need at least the last 2 cases to fail with a Jackson mapping related exception. The 3rd case may/may not fail (probably should fail, since the equals can get complex at times).
I tried checking if Jackson has anything that can be enabled/disabled in it's databind module's MapperFeatures but didn't have any luck.
I also tried checking in JsonParser.Feature & DeserializationFeature, but these deal more with parsing the actual Json input, rather than handling POJO / annotation processing, so I don't expect anything from in there...
This feature currently does not exist in Jackson.
Feature Request: https://github.com/FasterXML/jackson-databind/issues/3184

How to add description attribute while generating JSON schema from POJOs using codehaus package classes

I intend to convert my POJOs to a JSON Schema.
In the existing POJOs we have annotations from the codehaus package:
#JsonProperty("address") where the corresponding import is:
import org.codehaus.jackson.annotate.JsonProperty;
I can't use codehaus api to generate the schema as we have a recursive JSON structure and I get StackOverflowError.
So, I tried using the fasterxml's jackson-module-jsonschema API to do this which works fine.
Sample output that I'm getting:
"Registration" : {
"type" : "object",
"id" : "urn:jsonschema:com:xyz.abc.Address",
}
I have two requirements:
Apart from "type" and "id", I also want to have a description attribute. I can add #JsonPropertyDescription attribute, which would work, but then each property will have one annotation from codehaus and another one from the fasterxml package. Is there an equivalent annotation in codehaus which can be used for this purpose?
Is there a way to have just the un-qualified class name in the "id" attribute (only "Address" i.e. without the qualified object path "xyz.abc.Address" and without "urn:jsonschema") ?
Code for schema generation using fasterxml:
ObjectMapper mapper = new ObjectMapper();
JsonSchemaGenerator schemaGen = new JsonSchemaGenerator(mapper);
JsonSchema schema = schemaGen.generateSchema(DashboardDef.class);
String generatedJsonSchema = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema);
If it is possible just replace codehaus annotation by fasterxml one. codehaus is not supported anymore and should be avoided. For more info take a look at: org.codehaus.jackson versus com.fasterxml.jackson.core.
If you really want to dive into project with these two libraries you should take a look at AnnotationIntrospector class which allow extra configuration and linking many different libraries with Jackson framework. See similar question: How to make fasterxml ObjectMapper work with codehaus annotations.
To manipulate JSON Schema you can implement your own SchemaFactoryWrapper. See also:
Removing “id” from JSON schema when creating it from POJO using jackson.
Generating flat JSON schema with all $ref resolved from Java class #132
PS: I know this is not ideal answer (it does not contain direct solution) but I wanted point you some topics which you should start from to solve your problems, and comments are too small for this.

How do I avoid content fields in Joda objects?

I'm using Joda objects (DateTime and DateTimeZone) in a document and whenever I access it via the REST interface I get entries with fields like this
lastAggregationDate: { content: "2016-07-12T17:58:43.643Z" }
instead of
lastAggregationDate: "2016-07-12T17:58:43.643Z"
I have the Joda Jackson dependencies declared and I see the de/serializers for these types so I'm puzzled as to what's at work here.
I've duplicated this behavior in a slightly modified Spring sample project but using Java's native date types rather than Joda's. I've added a date of birth property to the Person object and modified the shouldRetrieveEntity test to look for $.dateOfBirth.content. I've confirmed the serializer is being used and it seems like the LocalDate object is being treated as a resource rather than as a simple property.
This is fixed in Spring Data Hopper-SR4:
https://jira.spring.io/browse/DATAMONGO-1498
The issue results from Spring Boot not setting up MongoMappingContext correctly. A ticket has been created for Spring Boot and the fix is anticipated for the 1.4.1 release (credit for this answer goes to Oyku Gencay and Oliver Gierke). For more detail, see the ticket or the pull request.

Hibernate hibernate.hbm2ddl.auto=create/update/validate doesn't work for correctly for custom dialects?

I recently upgrade Hibernate from version 3.3.x to 3.6.4. In version 3.3.x validateSchema (hibernate.hbm2ddl.auto=validate) works correctly.
In version 3.6.x validation is broken (tested for 3.6.4 and 3.6.7 as well). The issue is relevant only for field type text.
I redefined the SQL type in my dialect e.g.
public class SQLServer2000UnicodeDialect extends SQLServerDialect {
public SQLServer2000UnicodeDialect(){
super();
// Use Unicode Characters
...
registerColumnType( Types.CLOB, "ntext" );
...
}
}
But during validation, hibernate use original SQL types instead of customized!
Wrong column type in db.dbo.table_name for column a_column. Found:
ntext, expected: text
It looks like a bug, but not sure if it is. Maybe I'm missing something in configuration?
P.S. hibernate.hbm2ddl.auto=create/update doesn't works correctly also!
P.P.S. My XML mapping configuration:
<property name="propName" type="text" column="a_column"/>
Did you look at this It looks like something similar. And the author claims it is working. And this.
As to your question, I suspect that while validation your class is somehow left out. Did you wire up your class properly and is JAR in the classpath etc?
This message :
Found: ntext, expected: text
tells me that you have a property of type ntext somewhere. What I believe you should be doing is : to continue using hibernate types in your schema, and let hibernate handle converting the types into the database specific type using the dialect. Do not use custom types in XML mapping files.
It's a bit strange, but hibernate somewhere in versions 3.4-3.6 changed binding of "text" mapping (actually hibernate have two types of mapping for long strings: clob and text).
In version 3.3 both mapping (clob and text) were mapped to Types.CLOB.
In version 3.6 you have to provide separate mapping for text and for clob. Fixing my dialect as shown below solved my issue:
public class SQLServer2000UnicodeDialect extends SQLServerDialect {
public SQLServer2000UnicodeDialect(){
super();
...
registerColumnType( Types.CLOB, "ntext" );
registerColumnType( Types.LONGVARCHAR, "ntext" );
...
}
}

Categories

Resources