I am working on json currently in android, but now i follow getter and setter methods to parse json. For example. if there are 5 fields in json string, so create 5 getter and setter methods in one class and accordingly parse the string.
But now in future if one more field increases in json string, then again i need to add one more getter and setter method in that class.
So my question is can we parse json without getter setter, without any class? so that if json changes in future it can be handled well without adding new getter and setter method.
Please let me know the dynamic way to handle json.
you can use these web site http://www.jsonschema2pojo.org/
for creating a class if in future any field increase just put the json in that it will automatically create a class for you .
Related
While writing code for RecyclerView to get data I figured out there's a data class in Kotlin.
Following codes are taken from two different projects which are linked above.
#Serializable
data class MarsPhoto(
val id: String,
#SerialName(value = "img_src")
val imgSrc: String
)
class Contacts {
#SerializedName("country")
private val country:String? = null
fun getCountry():String?{
return country
}
}
I know that both classes are doing same job. So what does differentiate them? I also wonder in the MarsPhoto data class how they can get the id without declaring SerialName just the way they did for imgSrc. (I am just on the way to learning kotlin now, so I'm absolute beginner).
Basically for "data" class the compiler automatically derives the following members from all properties declared in the primary constructor:
equals()/hashCode() pair
toString() of the form "MarsPhoto(id=1, imgSrc=asdf)"
componentN() functions corresponding to the properties in their order of declaration.
copy()
You can read a lot more at enter link description here
On the SerializedName part of your question. if you are dealing with Gson lib by default it is using fields name as "SerializedName". And only if you want to use something different then field name, you can use SerializedName annotation and pass your custom value there. But usually, everybody just writes #SerializedName() with duplication of field names as value for every field.
It's a good idea if you are receiving and Serializing data from server from Json. Because Backend developers can use a bad keys in response, which you don't want to use in your code, so #SerializedName will be the only place where you will have to see this key, and you can name your fields however you like.
#Serializable used to mark class as serializable to disk or like into a file( alternative is Parcel able in android) special useful in case of process death or configuration changes and #SerializedName("country") used for json parsing when u receive the response from server
You get the id without #SerializedName because the JSON property field is the same as your variable name, but imgSrc and img_src is not. Still, even if they are the same, you should always use #SerializedName, because your variable names could be converted to random letters during code optimization, and obfuscation.
I am trying to parse the results of an API call which returns a unique first property.
{
"AlwaysDifferent12345": {
"fixedname1" : "ABC1",
"fixedname2" : "ABC2"
}
}
I am using retrofit2 and jackson/gson and cannot figure out how to cope with dynamic property names within the retrofit2 framework. The following works fine
data class AlwaysDifferentDTO(
#JsonProperty("AlwaysDifferent12345") val alwaysDifferentEntry: AlwaysDifferentEntry
)
I have tried
data class AlwaysDifferentDTO(
#JsonProperty
val response: Map<String, AlwaysDifferentEntry>
)
But this returns errors Can not instantiate value of type... The return value from the API is fixed i.e. map<string, object>.
I have read you can write a deserializer but it looks like I need to deserialize the whole object when all I want to do is just ignore the string associated with the response.
I have read
https://discuss.kotlinlang.org/t/set-dynamic-serializedname-annotation-for-gson-data-class/14758
and several other answers. Given unique properties names are quite common it would be nice to understand how people deal with this when using retrofit2
Thanks
Because the JSON doesn't have a 1-to-1 mapping Jackson can't map it automatically using annotations. You are going to need to make your own Deserializer.
In this tutorial you can learn how to create your own custom Deserializer for Jackson. https://www.baeldung.com/jackson-deserialization
In the tutorial you will see the first line under the deserialize function is
JsonNode node = jp.getCodec().readTree(jp);
using this line you can get the JSON node as a whole and once you have it you can call this function
JsonNode AlwaysDifferent12345Node = node.findParent("fixedname1");
Now that you have that node you can retrieve its value like shown in the rest of the tutorial. Once you have all the values you can return a new instance of the AlwaysDifferentDTO data class.
I need to parse only one list of objects from JSON object with Retroft.
Here's my JSON file
I need only "similar" array from it. Also I've already created POJO for elements of this array
Is there a way to make this without making POJO for the rest of the JSON file?
Just make pojo with necessary fields:
data class ServerResponse(
val recipe: RecipeResponse
)
data class RecipeResponse(
val similar: List<RecipeBrief>
)
I would like to parse a JSON object and map it to a RealmObject directly using the method createObjectFromJson.
My JSON is looking like that:
"data": {
"default": "a string"
}
So I make a RealmObject class like this
public class Data extends RealmObject{
private String default;
// GETTERS AND SETTERS
}
So I can call the method
realm.createObjectFromJson(Data.class, json);
Obviously the problem here is that I cannot use the keyword default to name my variable.
Is there any way to annotate my variable in Realm to use an alias ?
I'm aware that I can modify my input JSON but the aim is not to do it so I can have a generic method to map my JSON to a RealmObject.
Realm does not support renaming variables, but JSON libraries like GSON and Jackson do. You should look into those instead and then use copyToRealm or copyToRealmOrUpdate instead of createObjectFromJson
I have json with field that contains two different types.
"fields":[{"value":"ZIELONE OKO"},{"value":{"#nil":"true"}}]
I have problem with deserializing these. My class with model contains:
private String value;
And I simply need to translate {"#nil":"true"} into null. Right now I get error:
The JsonDeserializer StringTypeAdapter failed to deserialized json object {"#nil":"true"} given the type class java.lang.String
Ideally, I would change code that produces that odd JSON: shouldn't second value just be JSON null? I guess it is being produced by some complex process, starting with XML (which must use 'isNul' to differentiate between null String and empty String).
But if that is not possible, I think both Jackson and Gson would require either custom deserializer; or to first bind to a generic Map and then handle value oddities explicitly. In second case, you just declare type to bind to as Map (possible with generic type info using reference; but that should be optional).