Different Names of JSON Property During Serialization and Deserialization

Different names of JSON property during serialization and deserialization

Just tested and this works:

public class Coordinates {
byte red;

@JsonProperty("r")
public byte getR() {
return red;
}

@JsonProperty("red")
public void setRed(byte red) {
this.red = red;
}
}

The idea is that method names should be different, so jackson parses it as different fields, not as one field.

Here is test code:

Coordinates c = new Coordinates();
c.setRed((byte) 5);

ObjectMapper mapper = new ObjectMapper();
System.out.println("Serialization: " + mapper.writeValueAsString(c));

Coordinates r = mapper.readValue("{\"red\":25}",Coordinates.class);
System.out.println("Deserialization: " + r.getR());

Result:

Serialization: {"r":5}
Deserialization: 25

Different serialization/deserialization names with java jackson

You're on the right track. Here's an example of this working with a test JSON document.

public static class MyClass {
private String defaultReference;

@JsonProperty(value = "default_reference")
public void setDefaultReference(String defaultReference) {
this.defaultReference = defaultReference;
}

@JsonProperty(value = "defaultReference")
public String getDefaultReference() {
return defaultReference;
}

public static void main(String[] args) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
MyClass instance = objectMapper.readValue("{\"default_reference\": \"value\"}", MyClass.class);
objectMapper.writeValue(System.out, instance);
// Output: {"defaultReference":"value"}
}
}

Different names of JSON property during serialization and deserialization in golang

The standard lib does not support this out of the box, but using custom marshaler / unmarsaler you can do whatever you want to.

For example:

type Coordinates struct {
Red int `json:"red"`
}

func (c Coordinates) MarshalJSON() ([]byte, error) {
type out struct {
R int `json:"r"`
}

return json.Marshal(out{R: c.Red})
}

(Note: struct fields must be exported to take part in the marshaling / unmarshaling process.)

Testing it:

s := `{"red":12}`
var c Coordinates
if err := json.Unmarshal([]byte(s), &c); err != nil {
panic(err)
}

out, err := json.Marshal(c)
if err != nil {
panic(err)
}

fmt.Println(string(out))

Output (try it on the Go Playground):

{"r":12}

C# - Set different PropertyName between JSON serialization and deserialization

I solved it through WriteJson method as Chetan Ranpariya suggested:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JArray result = new JArray();

if (value.GetType().IsGenericType && value is IEnumerable)
{
IEnumerable list = value as IEnumerable;

foreach(var obj in list)
{
result.Add(GetObjectJson(obj));
}
}

result.WriteTo(writer);
}

private JObject GetObjectJson(object obj)
{
JObject jObj = new JObject();
PropertyInfo[] props = obj.GetType().GetProperties();

foreach (PropertyInfo prop in props)
{
if (!prop.PropertyType.ToString().Contains("System"))
jObj.Add(char.ToLowerInvariant(prop.Name[0]) + prop.Name.Substring(1), GetObjectJson(prop.GetValue(obj)));
else
jObj.Add(char.ToLowerInvariant(prop.Name[0]) + prop.Name.Substring(1), JToken.FromObject(prop.GetValue(obj)));
}

return jObj;
}

As in object value parameter I receive the object (which is a list, in this case) I cast it and iterate over it's objects.

Since every object can have primitive and non primitive properties, I created a separated function to use it recursively in case I found a nested object.

How to use different JSONProperty on Serialize & Deserialize using Jackson API?

Googling around i have found solution for it.
We can use @JsonAlias using latest Jackson API (2.9.7)
So in my case i wanted this alias for deserialization @JsonAlias(value={"author","authorList"}).

JSON Jackson parse different keys into same field

Use different name for serializing and deserializing with Json.Net

You can make use of the JsonSerializerSettings, the ContractResolver and the NamingStrategy.

public class ErrorDetails
{
public int Id { get; set; }
public string ErrorMessage { get; set; }
}

var json = "{'Id': 1,'error_message': 'An error has occurred!'}";

For dezerialization you could use the SnakeCaseNamingStrategy.

var dezerializerSettings = new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
}
};
var obj = JsonConvert.DeserializeObject<ErrorDetails>(json, dezerializerSettings);

To serialize the object again you dont have to change the JsonSerializerSettings as the default will use the property name.

var jsonNew = JsonConvert.SerializeObject(obj);

jsonNew = "{'Id': 1,'ErrorMessage': 'An error has occurred!'}"


Or you could create a contract resolver which can decide which name to use. Then you can decide when you dezerialize and serialize if you want to use the pascal case name format or the one with the underscore.

public class CustomContractResolver : DefaultContractResolver
{
public bool UseJsonPropertyName { get; }

public CustomContractResolver(bool useJsonPropertyName)
{
UseJsonPropertyName = useJsonPropertyName;
}

protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (!UseJsonPropertyName)
property.PropertyName = property.UnderlyingName;

return property;
}
}

public class ErrorDetails
{
public int Id { get; set; }
[JsonProperty("error_message")]
public string ErrorMessage { get; set; }
}

var json = "{'Id': 1,'error_message': 'An error has occurred!'}";
var serializerSettings = new JsonSerializerSettings()
{
ContractResolver = new CustomContractResolver(false)
};
var dezerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CustomContractResolver(true)
};

var obj = JsonConvert.DeserializeObject<ErrorDetails>(json, dezerializerSettings);
var jsonNew = JsonConvert.SerializeObject(obj, serializerSettings);

jsonNew = "{'Id': 1,'ErrorMessage': 'An error has occurred!'}"

Jackson: Serialize/deserialize with different property name

Try using a different JsonProperty annotation for the getter and the setter. E.g.

@JsonProperty("tagnameOpc")
void setTagName(String name)

@JsonProperty("tagName")
String getTagName()

If that doesn't work try with an extra setter

@JsonIgnore
void setTagName(String name)

@JsonProperty("tagnameOpc")
void setTagNameOpc(String name) {
setTagName(name);
}

@JsonProperty("tagName")
String getTagName()

Jackson Serialize Field to Different Name

I am not sure I completly understand your question, but for what I could understand you can do something like this to achieve different serializtions.

Create a custom annotation to hold all possible different serialization options:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomJsonProperty {
String propertyName();

String format();

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface List {
CustomJsonProperty[] value();
}

}

Annotate your class accordingly:

@JsonSerialize(using = CustomJsonPropertySerializer.class)
public class Bar {

@CustomJsonProperty.List({
@CustomJsonProperty(propertyName = "first-name", format = "A"),
@CustomJsonProperty(propertyName = "firstName", format = "B")
})
private String firstName;

@CustomJsonProperty.List({
@CustomJsonProperty(propertyName = "last-name", format = "A"),
@CustomJsonProperty(propertyName = "lastName", format = "B")
})
private String lastName;

@CustomJsonProperty.List({
@CustomJsonProperty(propertyName = "gender-x", format = "A"),
@CustomJsonProperty(propertyName = "gender", format = "B")
})
private String gender;

@JsonIgnore
private String format;

//getters & setters

}

Create a custom serializer to interpret your new annotation:

public class CustomJsonPropertySerializer extends JsonSerializer<Bar> {

@Override
public void serialize(Bar bar, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
jsonGenerator.writeStartObject();

Field[] fields = bar.getClass().getDeclaredFields();

for (Field field : fields) {
field.setAccessible(true);
Object value = null;

try {
value = field.get(bar);
} catch (IllegalAccessException e) {
e.printStackTrace();
}

if (field.isAnnotationPresent(CustomJsonProperty.List.class)) {
CustomJsonProperty[] properties = field.getAnnotation(CustomJsonProperty.List.class).value();
CustomJsonProperty chosenProperty = null;

for (CustomJsonProperty c : properties) {
if (c.format().equalsIgnoreCase(bar.getFormat())) {
chosenProperty = c;
break;
}
}

if (chosenProperty == null) {
//invalid format given, use first format then
chosenProperty = properties[0];
}

jsonGenerator.writeStringField(chosenProperty.propertyName(), value.toString());
}
}

jsonGenerator.writeEndObject();
}
}

Now you can serialize your objects taking into consideration different formats for the property names:

public static void main(String[] args) throws IOException {
Bar bar1 = new Bar("first", "last", "m", "A");
Bar bar2 = new Bar("first", "last", "m", "B");

ObjectMapper mapper = new ObjectMapper();
String json1 = mapper.writeValueAsString(bar1);
String json2 = mapper.writeValueAsString(bar2);

System.out.println(json1);
System.out.println(json2);

}

Output:

{"first-name":"first","last-name":"last","gender-x":"m"}
{"firstName":"first","lastName":"last","gender":"m"}

Of course the above serializer only works for Bar objects, but that can easily be solved using inheritance with abstract String getFormat(); on the super class and changing the custom serializer to accept the super class type, instead of Bar.

Maybe there is a simpler way than creating your own stuff, but I don't know about it. Let me know if something wasn't clear and I can elaborate it again.



Related Topics



Leave a reply



Submit