I have JAXB annotated class which i am trying to convert to JSON using jackson objectMapper. The issue with generated json is jackson is introduction a new property value:"xxx" for XMLValue annotation which is dont value. for example it is generated as below
{
"employeeName":
{
"value":"ABC"
}
}
but i want it as {"employeeName":"ABC"} instead
One more thing is while it wraps the arrays i am getting as below in the generated json
{
"Employers":{
"Employer":[
{
"name":"ddd"
}
]
}
instead i want it as only
{"Employer":[{"name":"ddd"}]}
Can someone suggest if above two are possible with jackson.
Yes, this is possible. It might be helpful when you provide your class so you could get a more specific answer which might use annotations. But at least you could write a custom serializer. If you do so you have full control over the produced json.
Related
I need to (de)serialize to and from JSON some of the data classes that are generated by a Gradle plugin. Normally I would just use a library like Moshi or kotlinx.serialization and add the proper annotation to the class I want to serialize but, since this data classes are autogenerated, this is a problem.
I would like to avoid manually to map all the fields of the generated data class to some other class that I can (de)serialize, or to write a custom adapter for all these data class so, I was wondering if there is another way to tell, for example, kotlinx.serialization that a class is #Serializable without having to put the annotation directly on top of the class itself.
Or, alternatively, is there a better way to convert to and from a string an instance of a generated data class?
kotlinx.serialization supports generating serializers for 3rd party classes. We need to use forClass parameter in #Serializer, for example:
data class MyData(val data: String)
#Serializer(forClass = MyData::class)
object MyDataSerializer
fun main() {
val data = MyData("foo")
println(Json.encodeToString(MyDataSerializer, data))
}
You can read more in the official documentation: https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/serializers.md#deriving-external-serializer-for-another-kotlin-class-experimental
I am totally new to Android and Kotlin and I was looking into Android Annotations.
I managed to decode a JSON response using the following code:
class ExampleModel {
#JvmField
final var id: Int = 0
lateinit var title: String
var description: String? = null
var author: Author? = null
}
#Rest(
rootUrl = "...",
converters = [MappingJackson2HttpMessageConverter::class]
)
interface ExampleClient {
#Get("/promotions")
fun getModels(): List<ExampleModel>
}
Now it does work but there are a couple of questions I'd like to ask.
Is it possible to use data classes? I tried but I kept getting an error from MappingJackson2HttpMessageConverter saying that there was no constructor available.
Is it somehow possible to just ignore extra keys that might appear in the JSON? Let's say that I am not interested in the author data for now, is there a way to just remove its declaration without having the decoding fail with "unexpected key"?
Consider that I usually work with Swift so if you could point me to the "Codable" equivalent in Kotlin I would really appreciate it.
Cheers
Kotlin Data classes don't have default constructor which is usually required by json deserialization libraries. Any data class require at least one constructor argument, but you can work around it. Define default values, you can use null. For example:
data class Pojo(val name: String? = null, val age: Int? = null)
Such code will allow to use Pojo() constructor. It should work, but it's better to use json deserializer that is more kotlin native or generate data classes with AutoValue.
Jackson that you're using here allows to ignore fields with #JsonIgnoreProperties.
If you're learning Android, don't start from Android Annotations if you don't have to. It's not very popular or modern solution. I used it in few projects back in the day, those were very difficult to maintain or to introduce new developers. Look into android architecture components and jetpack - google made few nice code labs. Also for json pick Moshi or Gson.
I just started developing in Java and chose Jersey (2.4.1) as the framework I will use to build restful services.
When serializing a model, is there any annotation (moxy or jackson) to not serialize a property only if the value is default?
For example, in the case of reference types this would be null, but in the case of an int or long, the default value is 0.
Is this possible?
Just figured this out. Using Jackson, you would use the following annotation:
#JsonSerialize(include=JsonSerialize.Inclusion.NON_DEFAULT)
public class User
{
...
}
Haven't figured out MOXy yet, however.
I would like to leverage the Jackson infrastructure to transform an untyped Map/List structure into a POJO hierarchy.
What I need is pretty close to
jsonNode = objectMapper.valueToTree(MapHierarchy) followed by
pojoTree = objectMapper.treeToValue(jsonNode)
...except that I need to modify the field names on the fly: the names found in the source Map/List hierarchy are declared as custom annotations on the POJO class.
Here is a complete example:
public class Cat
{
#MapField("attr:col")
#JsonProperty("color")
private String _color;
}
... and the source Map:
{
"attr:col" -> "black"
}
... from which I would like to obtain a Cat instance.
I am sure there has got to be an elegant way to achieve this with the Jackson APIs, but I can't quite figure out how... any suggestions? Obviously I don't want to create a second parallel class hierarchy just to describe the deserialization of the Map through annotations.
An extra bonus would be to be able to transform the Map without going through stringified JSon which I believe is how valueToTree works.
This question already has an answer here:
Newtonsoft JSON.net deserialization error where fields in JSON change order
(1 answer)
Closed 6 years ago.
I have the following method in my web api
public void Put(string id, [FromBody]IContent value) {
//Do stuff
}
I'm using backbone js to send the following JSON to the server using fiddler the value is null:
{
"id": "articles/1",
"heading": "Bar",
"$type": "BrickPile.Samples.Models.Article, BrickPile.Samples"
}
but if I add the $type property first in the JSON object the deserialization works fine, see:
{
"$type": "BrickPile.Samples.Models.Article, BrickPile.Samples",
"id": "articles/1",
"heading": "Bar"
}
is it possible to configure newtonsoft to check for the $type property anywhere in the object instead of the first property or can I configure backbone so it always adds the $type property first in the JSON object?
I would very strongly recommend against configuring any serializer (including JSON.NET) to read the object type from the incoming payload. This has historically been the cause of a large number of vulnerabilities in web applications. Instead, change the public entry point to your action to take the actual type as a bound parameter, then delegate to an internal testable method if desired.
First, AFAIK, the code of Json.NET is optimized to avoid holding the whole object in memory just to read its type. So it's better to place $type as the first property.
Second, you can write your own JsonConverter which reads first to JObject (using Load method), manually reads $type property, gets type from serializer's SerializationBinder, creates the value and populates it from JObject.
Third, regarding security. While Json.NET's $type may sound like a good idea, it's often not. It allows Json.NET to create any object type from any assembly just by writing its type in JSON file. It's better to use custom SerializationBinder with a dictionary which allows only types which you specify. You can find an example in my private framework (it also supports getting values for $type from JsonObjectAttribute):
https://github.com/Athari/Alba.Framework/blob/742ff1aeeb114179a16ca42667781944b26f3815/Alba.Framework/Serialization/DictionarySerializationBinder.cs
(This version uses some methods from other classes, but they're trivial. Later commits made the class more complex.)
I had kind of the same question apparently, and someone found an answer. Not sure whats the appropriate way to share an answer and give him ALL the credit, but this is the link:
Newtonsoft JSON.net deserialization error where fields in JSON change order
and this is the guy:
https://stackoverflow.com/users/3744182/dbc
This will work in backbone, but I don't know if every browser will behave the same. There's no guarantee, basically, that every browser will keep the items in the order which they are added.
MyModel = Backbone.Model.extend({
// ...
toJSON: function(){
// build the "$type" as the first parameter
var json = {"$type": "BrickPile.Samples.Models.Article, BrickPile.Samples"};
// get the rest of the data
_.extend(json, Backbone.Model.prototype.toJSON.call(this));
// send it back, and hope it's in the right order
return json;
}
});
You're better of getting NewtonSoft's JSON deserializer to work without needing it in a specific position, though. Hopefully that will be possible.