Jackson Serializing Object as String - java

so I have an Item class which looks like this(extra stuff excluded):
{
"id": 1,
"item": "something",
"account": {
"id": 5,
"name": "somename"
}
}
I want the owner tap to appear for example like this
{
"id": 1,
"item": "something",
"account": "somename"
}
I know how to do this by changing the way Item is serialized in Jackson, however if I am to change the way I serialize Item, I will have to include all the extra fields it has, also Item is a base class so I have to do something with all the child classes as well, which is too much work (or is it, dunno if anyone has an easy solution how to serialize just one field and include all the rest). So my question is can I just serialize the Account class and make it return a simple String (not a json object or anything like that).
I've tried working around with the JsonGenerator to make it look similar but the best I've got to so far is:
{
"id": 1,
"item": "something",
"account": {"account":"somename"}
}
Thanks!

I think what you want is #JsonIdentityInfo from Jackson.
This annotation allows you to specify how a child entity is serialized in a parent entity.
Here is an example:
#JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="productDescription")
#JsonIdentityReference(alwaysAsId=true) // otherwise first ref as POJO, others as id
private Product product;
This tells Jackson that the product bean should be serialized using its "productDescription" field.
You can also check this tutorial:
http://www.baeldung.com/jackson-annotations

Scratch that, I've found my mistake was that I always started with:
jsonGenerator.writeStartObject();
and ended with:
jsonGenerator.writeEndObject();
which itself made it return an object. All I had to do is just use the writeString method.

Related

Jackson treat field as object and include annotation in value

I have an interesting problem and not sure what the best way to design it. Would appreciate any inputs.
I have a bean class that needs to be converted to Json. The problem is that the field have custom property annotations.
#Descriptors(type="property", dbColumn="currency")
private String currency = USD; //(initializing for brevity)
I want Json that looks like this:
{
"currency": {
"type": "property",
"dbColumn": "currency",
"value": "USD"
}
}
Verbose way is to create a util triad and convert annotations into fields and then use that for json. Is there any other better way to achieve this.

How to set the type for a variable I post to a Sprint REST API?

I couldn't think of a good title for this question, my apologies. I hope my explanation clears things ups.
I've started using Spring yesterday. I'm currently trying to do something that probably has been asked before, but English isn't my first language and I can't find the right words to Google my answer. If you can refer me to a question where this has been asked before that would be great too.
The idea is that someone can POST information to the REST API I made with Spring, but the data type of the accompanying value(s) can be a string, boolean or number/integer. The JSON I post looks like this at the moment:
{
"values": [
{
"name": "temp",
"type": "number",
"value": 25
},
{
"name": "zone",
"type": "string",
"value": "Test String"
}
]
}
I have set up two models, one "main" model which currently holds an array of Value classes. The Value classes hold the information of each value from the "values" array in the JSON:
public class HeadComponent {
//This class will get some other fields later
public Value[] values;
public HeadComponent() {
}
}
public class Value {
public String name, type, value;
public Value() {
}
}
When I return the object via a route every value gets converted to a String, which isn't surprising of course, considering I made every field a String in the model.
{
"values":[
{
"name":"temp",
"type":"number",
"value":"25"
},
{
"name":"zone",
"type":"string",
"value":"Test String"
}
]
}
I'm trying to figure out the best way to handle different types within one model. Should I keep my Value class this way and manually try converting the values in the back-end? Does Spring happen to have a feature which allows me to have multiple types for a variable? Or do you have any other things I can look into?
I hope this wasn't too confusing, thanks in advance!

Jackson CustomSerializer for specific fields

I have a requirement to take a document with ~60 fields and map it to a customer schema. Our schema has one field that I have as an array like so:
"documents": [{
"type": "Resume",
"url": "https://.s3.amazonaws.com/F58723BD-6148-E611-8110-000C29E6C08D.txt"
}, {
"type": "Reference",
"url": "https://.s3.amazonaws.com/F58723BD-6148-E611-8110-000C29E6C08D.txt"
}]
I need to transform that to:
"document1": {"type":"Resume", "https://.s3.amazonaws.com/F58723BD-6148-E611-8110-000C29E6C08D.txt"}
"document2": {"type":"Reference", "url":"https://.s3.amazonaws.com/F58723BD-6148-E611-8110-000C29E6C08D.txt"}
I've started a cumstom serializer but would really, really like to not have to write a custom serializer for all 60 fields to just do that one transform. Is there a way to tell jackson to serialize all other fields as normal and use my logic for just this one instance?
I have tried a number of options and keep getting the ever-so-helpful error:
com.fasterxml.jackson.core.JsonGenerationException: Can not write a field name, expecting a value
If I could even determine what this means it would be greatly helpful.
Thanks in advance!
A possible solution is to have the cumstom serializer call the default serializer for all those fields that can undergo default serialization.
See this thread for how to do it How to access default jackson serialization in a custom serializer
If you create, from the input, a map where the values are a string with raw Json, you can use the custom serializer written by Steve Kuo in Jackson #JsonRawValue for Map's value

Nested specific type de-serialization with Avro

Here is the related part of the schema that I am using to generate my Avro class
{"namespace": "com.namespace.kafka.event",
"type": "record",
"name": "RecordName",
"fields": [
// some fields declared
...
{"name": "products", "type": { "type": "array", "items":
{
"name": "productInfo",
"type": "record",
"fields" : [
{"name": "productId", "type": "int"},
{"name": "productScore", "type": "float"}
]
}
}
},
// some more fields declared
...
]
}
I am able to generate classes for this schema and to populate them. So basically in the generation a new class called productInfo is generated which serves my needs. (Later I send the data to Kafka). The problem is the de-serialization. I am using something like this:
GenericData.Array<String> productTuple = (GenericData.Array<String>) record.get("products");
This returns me a string (which is actually a JSON) like this for each element of GenericData array.
{"productName" : someName, "productScore" : someScore }
I can parse this string and get what I want but is there a more "Avro" way of doing this. Like can I cast the results again to a GenericRecord object like this.
GenericData.Array<GenericRecord> productTuple = (GenericData.Array<GenericRecord>) record.get("products");
or will this work where productInfo being the class generated from my avro schema:
GenericData.Array<productInfo> productTuple = (GenericData.Array<productInfo>)
Unfortunately, I cant test it I dont have an easy setup to do so. I searched the whole web but could not find a way to do that. Any help will be much appreciated.
The right way to do it was to use :
GenericData.Array<GenericRecord> productTuple =(GenericData.Array<GenericRecord>) record.get("products");
I believe the last one might work as well but this one lets me deserialize the JSON without any further interference from a class.

Deserialize self referencing objects with Jackson

I have a JSON string looking like that (simplified):
[
{ "id":1, "friends":[2] },
{ "id":2, "friends":[1,3] },
{ "id":3, "friends":[] }
]
The content of friends are ids of other users in the list.
Is it possible somehow to create a Java class like the one below from the JSON just with Data Binding using Jackson or do I need an intermediate step for that?
public class User {
private long userid;
private List<User> friends;
// ... getters/setters
Thanks for your help.
There is no fully annotative way to do this, so you would need custom JsonSerializer / JsonDeserializer. Jackson 1.9 adds two new features that might help:
ValueInstantiators, so you can add constructors for deserializer to convert from basic integer into POJO
Value injection so you could pass additional context object (which you would need to find ids of already deserializer objects, to map then from integer to instance)
However I am not 100% sure how to combine these two features for specific use case...

Categories