Simplest custom serialization in Jackson? - json

I have an EntityId class that servers as a simple wrapper class to database identifiers. The class already has methods for converting to and from a string representation. I'd like to use this string representation of the EntityId in my JSON web resources.
What's the simplest to implement custom serialization for this simple type in Jackson? I know I can write a custom serializer and deserializer, but I wondered if there might be an even simpler solution.
Thanks!

If there is a method to serialize type as String, you can just add #JsonValue annotation like so:
public class MyClass {
#JsonValue public String toString() { return "xxx"; }
}
Conversely, if there is a single-arg constructor that takes a String, int or long (or some Java type that Jackson can convert to from JSON Scalar type), you can add #JsonCreator annotation next to that constructor:
public class MyClass {
#JsonCreator
public MyClass(OtherPojo value) { // or use 'Map<String,Object>', extract data
// ...
}
}

Related

Dart: how to use json_serializable library to create different subclasses from the json input

UML
I have to serialize json in order to create specific subclass from the Enum which is an attribute of one class that contains the abstract class target
class Test {
Outcome outcome;
TestType type;
}
abstract class Outcome {
String attribute;
}
class PackageOutcome extends Outcome {
String packageAttribute;
}
class FlexibilityOutcome extends Outcome {
String flexibilityAttribute;
}
Outcome doesn't have factory methods to serialize json, but PackageOutcome and FlexibilityOutcome have it.
in factory method Test.toJson() if I have a specific type of Enum TestType I crate PackageOutcome and if I've another type I create FlexibilityOutcome as Outcome of Test.
you can do this with json_serializable?
There are some tutorials that explain how to do that?

Jackson deserialization when POJO does not match JSON structure

I have some json :
{
key: "CORE-19",
fields: { summary: "iblah" }
}
I want to pack it into a POJO that looks more like:
#JsonIgnoreProperties(ignoreUnknown=true)
public class JiraIssue
{
private String mKey;
private String mSummary;
public String getKey(){ return(mKey);}
public void setKey(String inKey){mKey = inKey;}
public String getSummary(){return(mSummary);}
public void setSummary(String summary){ mSummary = summary; }
}
So basically I don't want to create a 'Fields' object as it is a bit superfluous for my needs. However I really can't see any way in Jackson to tell it that the 'summary' property actually comes from the 'fields' property. Is this possible?
Serialization of this class is not a concern, it will only ever be used for Deserialization. I have no control over the JSON format as it is coming from an external source (and the above is just a snippet). Also I'm actually using Jackson with Jersey.
Thanks!
There is actually an open issue for this kind of structural change. There is no way as of now to do that easily with annotation only without modifying your class. What you could do instead is handle the "fields" property as a "false" property, by adding the following method:
public void setFields(Map<String, String> fields) {
setSummary(fields.get("summary"));
}
This way you "unwrap" the property yourself.
Try:
#JsonProperty("fields.summary")
private String mSummary;

Gson deserialisation returns null

I have a problem on converting JSON string to object in Android. Here are the JSON structure and Java classes:
JSON:
{
"code":"SUCCEED",
"message":"",
"result":{
"ccahUserId": 111,
"ccahUserName":"your_name",
"userFirstName":"your_first_name",
"userLastName":"your_last_name",
//others
}
Java classes:
public class Result<T>{
public String code;
public String message;
public T result;
}
public class DeviceSetting
{
public long ccahUserId;
public String ccahUserName;
public String userFirstName;
public String userLastName;
//other members
}
Activity:
Gson gson = new Gson();
Result<DeviceSetting> setting = gson.fromJson(result, Result<DeviceSetting>.class);
When I deserialise the JSON string, code and message field were good but result field is null.
I am not familiar with Gson yet, so please help how to fix this problem?
Thanks in advance.
Likely the result field is null because it relies on the type parameter for Result.
From the GSON documentation for Gson.fromJson(JsonElement, Class<T>) (bolding is mine):
This method deserializes the Json read from the specified parse tree
into an object of the specified type. It is not suitable to use if the
specified class is a generic type since it will not have the generic
type information because of the Type Erasure feature of Java. Therefore, this method should not be used if the desired type is a generic type. Note that this method works fine if the any of the fields of the specified object are generics, just the object itself should not be a generic type. For the cases when the object is of generic type, invoke fromJson(JsonElement, Type).

How do I omit the assembly name from the type name while serializing and deserializing in JSON.Net?

We have a single contract assembly which has all our data contracts. We are using JSON.net for serializing our data contracts to json.
JSON.Net adds both the type name and the assembly name in the $type attribute on serialization. Since all our data contracts are in the same assembly which is always loaded in the current app domain, we should be able to omit this.
How can we achieve this?
Thanks
You can use the Binder property in your JsonSerializerSettings.
This blog post (by the library author) describes the steps: http://james.newtonking.com/archive/2011/11/19/json-net-4-0-release-4-bug-fixes.aspx
In short, you create a custom class deriving from SerializationBinder and override two methods:
BindToName(Type serializedType, out string assemblyName, out string typeName)
BindToType(string assemblyName, string typeName)
The logic you place in those methods will give you direct control over how type names are converted to string representation in the $type field, and how types are located at run-time given values from $type.
In your case, wanting to omit the Assembly name, you can probably do:
public override void BindToName(
Type serializedType, out string assemblyName, out string typeName)
{
assemblyName = null;
typeName = serializedType.FullName;
}
public override Type BindToType(string assemblyName, string typeName)
{
return Type.GetType(typeName);
}
I think maybe tag the class with the JsonObjectAttribute
[DataContract]
[JsonObject("")]
public class MyContractClass { ... }
This should override the fact that it is also a DataContract.

How to write custom serializer and deserializer in Jackson?

I have a class that has more than a dozen properties. For most of the properties of primitive type, I hope to use the default BeanSerializer and BeanDeserializer or whatever to reduce the cumbersome code I need to write. For other properties of custom and array types, I want to do some custom serializer/deserializer. Note that I am not able to change the underlying JSON string. But I have full access to the android code. I am using Jackson 1.7.9/Ektorp 1.1.1.
shall I subclass BeanDeserializer? I am having trouble with that. It expects a default constructor with no parameters but I don't know how to call the super constructor.
class MyType{
// a dozen properties with primitive types String, Int, BigDecimal
public Stirng getName();
public void setName(String name);
// properties that require custom deserializer/serializer
public CustomType getCustom();
public void setCustom(CustomType ct);
}
class MyDeserializer extends BeanDeserialzer{
// an exception is throw if I don't have default constructor.
// But BeanDeserializer doesn't have a default constructor
// It has the below constructor that I don't know how to fill in the parameters
public MyDeserializer(AnnotatedClass forClass, JavaType type,
BeanProperty property, CreatorContainer creators,
BeanPropertyMap properties,
Map<String, SettableBeanProperty> backRefs,
HashSet<String> ignorableProps, boolean ignoreAllUnknown,
SettableAnyProperty anySetter) {
super(forClass, type, property, creators, properties, backRefs, ignorableProps,
ignoreAllUnknown, anySetter);
}
#Override
public Object deserialize(JsonParser jp, DeserializationContext dc, Object bean)
throws IOException, JsonProcessingException {
super.deserialize(jp, dc, bean);
MyType c = (MyType)bean;
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readValue(jp, JsonNode.class);
// Use tree model to construct custom
// Is it inefficient because it needs a second pass to the JSON string to construct the tree?
c.setCustom(custom);
return c;
}
}
I searched Google but couldn't find any helpful examples/tutorial. If anyone can send me some working examples that would be great! Thanks!
To sub-class BeanSerializer/-Deserializer, you would be better off using a more recent version of Jackson, since this area has been improved with explicit support via BeanSerializerModifier and BeanDeserializerModifier, which can alter configuration of instances.
But just to make sure, you can also specify custom serializer/deserializer to just be used on individual properties, like so:
class Foo {
#JsonSerialize(using=MySerializer.class)
public OddType getValue();
}