How to work with dynamic SerializedName annotation? - java

I have a json that i transform with gson in a realm model, over the annotaion #SerializedName.
But sometime in the json, there is a unknown key, that i want to serilized to a string.
public class example extend Realmobject{
#SerializedName("example1")
#Expose
private String exampleNr1;
#SerializedName("example2")
#Expose
private String exampleNr2;
private String someOtherValue;
Getter / Setter here...
}
The Json is like this
[
{
"example1": "1234",
"example2": "1234",
"x": "dynamic"}, {
"example1": "1454",
"example2": "165456",
"xy": "dynamic"}]
Now i will to Serialized the x and xy Key (somtimes is named xyz and so on) to the someOtherValue String.
Over the #SerializedName(value="", alternate={""}) I have no chance, because, i dont know the name of the field.
i Serialize this over
List woList = gson.fromJson(parentArray,
new TypeToken>() {}.getType());

You could translate it to a JSONObject first. Then you can loop through the set of keys inside the JSONObject.
JSONObject json = gson.fromJson(stringJson, JSONObject.class);
Iterator<String> set = json.keys();
while(set.hasNext()) {
String dynamicAttributeName = set.next();
}
json.get(dynamicAttributeName); //to get the value

Related

DynamoDB nested map to Java Object

I am using a DynamoDB-table with DynamoDBAttributeType.M maps nested in one another. The field of my table I'm having problems with looks like this:
"Data": {
"EnglishName": "Balcony",
"High": {
"Status": true,
"Triggered": true,
"Value": 5
},
"Low": {
"Status": true,
"Triggered": false,
"Value": 1
},
"TagName": "tag1"
}
all the keys of the map are Strings and some of the values are Strings and some are maps. In my Java code that data is represented by a class, which is an attribute of another class, which represents whole table. Attributes 'Low' and 'High' are also represented by Java class and attributes of data class.
I have tried to map it to Java object using many ways, mostly by DynamoDBTypeConverter. Hardest part is that I can't find any information about this with Google. I only found one example of converter class where attribute type is S not M.
I keep on getting error:
could not unconvert attribute
How this can be done?
Finally I have a functioning solution. Basically the answer is to use Map<String, Attributevalue> and desired object type in DynamoDBTypeConverter like this:
public class DataConverter implements DynamoDBTypeConverter<Map<String, AttributeValue>, Data> {
#Override
public Map<String, AttributeValue> convert(Data data) {
ObjectMapper mapper = new ObjectMapper();
Item item = new Item()
.withString("englishName", data.getEnglishName())
.withMap("high", mapper.convertValue(data.getHigh(), Map.class))
.withMap("low", mapper.convertValue(data.getLow(), Map.class))
.withString("tagName", data.getTagName());
return ItemUtils.toAttributeValues(item);
}
#Override
public Data unconvert(Map<String, AttributeValue> data) {
Data tagData = new Data();
try {
ObjectMapper mapper = new ObjectMapper();
String item = ItemUtils.toItem(data).toJSON();
JsonNode json = mapper.readTree(item);
tagData = mapper.convertValue(json, Data.class);
} catch (JsonProcessingException ex) {
Logger.getLogger(TagDataConverter.class.getName()).log(Level.SEVERE, null, ex);
}
return tagData;
}
I also needed to write type converters to attributes that are objects and annotate them in class:
public class Data {
private String tagName;
private String englishName;
#DynamoDBTypeConverted(converter = AlertConverter.class)
private Alert low;
#DynamoDBTypeConverted(converter = AlertConverter.class)
private Alert high;
The AlertConverter.class is an ordinary DynamoDBTypeConverter that takes in <String, Alert>.
Have you tried using a tool like Gson? If you're getting back the DynamoDB response as a JSON string, try this:
Gson gson = new Gson();
Data data = gson.fromJson(jsonString, Data.class);

How to process an associative array from JSON in Android Java

I am trying to process the JSON output from https://api.exchangeratesapi.io/latest in my Android app, which is returned in this format:
{
"rates": {
"CAD": 1.5613,
"HKD": 8.9041,
...
"KRW": 1374.71,
"MYR": 4.8304
},
"base": "EUR",
"date": "2020-03-09"
}
I would like to use GSON to process this JSON, so I have added a class ExchangeRates to recieve the data:
class ExchangeRates {
private String base;
private String date;
}
These commands load the JSON into my ExchangeRates class:
Gson gson = new Gson();
ExchangeRates mExchangeRates = gson.fromJson(result, ExchangeRates.class);
However, I cannot figure out how to load the associative array of exchange rates into the class in a scalable manner. I know I could add a static list of the currencies, but I want the code to be able to automatically handle additional currencies if they are added at a later date.
It turned out to be very simple, and yes, #ya379, a HashMap was part of the answer. Given a HashMap data type, GSON will translate the associative array part of the JSON directly to a HashMap:
class ExchangeRates {
private String base;
private String date;
private HashMap<String, Double> rates;
}

Map enveloped response into a POJO

I am trying to map the following response:
{
"data": {
"id": "1574083",
"username": "snoopdogg",
"full_name": "Snoop Dogg",
"profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_1574083_75sq_1295469061.jpg",
"bio": "This is my bio",
"website": "http://snoopdogg.com",
"counts": {
"media": 1320,
"follows": 420,
"followed_by": 3410
}
}
into an object where I only want to retrieve the username, full_name, and id fields.
Ex: something like:
public class User{
String id;
String username;
String full_name;
// getters + setters
}
Is there a way of doing this without first having to store the data object into a Map?
Use Jackson API. It should be simple:
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(jsonString, User.class); //jsonString is your actual json string.
You might want to tweak your User class to match the JSON string. E.g. your user class needs to have a 'data' field as List<Data> data; where 'Data' is another POJO. You can add the "id", "userName", etc fields in the 'Data' pojo.
You can either do it by hand via, for example, regexp or utilize any of JSON libraries like Jackson, GSON etc.
With GSON it's pretty simple. Say your json is stored in a String jsonString variable.
Gson gson = new Gson();
YourObject = gson.fromJson(jsonString, YourObject.class);
Although I'm not sure what will happen, since your jsonString doesn't have a key called User. However, this should work if you first extract data from your jsonString and name your POJO Data.

gson JSON to Java -- json property has . or - in it

What steps will reproduce the problem?
1.I have a json reponse as
String Content =
"{
"region":{
"state.code":"TX",
"country-code":"USA"
}
}";
2.I want to convert this Json Object into Java Object.I have this Java class to convert
public class Region{
private String stateCode;
private String countryCode;
public String getStateCode ()
{
return stateCode;
}
public void setStateCode (String stateCode)
{
this.stateCode = stateCode;
}
public String getCountryCode ()
{
return countryCode;
}
public void setCountryCode (String countryCode)
{
this.countryCode = countryCode;
}
}
3.My problem is Java doesnt allow . or - in variable name.Which doesnt allow json string to map to Region java class object giving null .
gson.fromJson(Content, Region.class);
What is the expected output? What do you see instead?
Can anybody please help me in this?
I have tried #SerializedName annotations but it is not working.
What version of the product are you using? On what operating system?
Please provide any additional information below.
You're trying to map this JSON
{
"region":{
"state.code":"TX",
"country-code":"USA"
}
}
to an instance of type Region. That JSON is a JSON Object which contains a pair with name region and a value which is a JSON Object. That JSON Object has two pairs, one with name state.code and JSON String value TX and one with name country-code and JSON String value USA.
You can't map that to a Region object. You have to bypass the root's pair named region.
Create a encapsulating type
class RegionContainer {
private Region region;
// the rest
}
and map that
gson.fromJson(Content, RegionContainer.class);
#SerializedName will work for your fields.
#SerializedName("state.code")
private String stateCode;

GSON mapping null value for POJO properties

I'm trying to use GSON 2.2.2 (for the very first time) to map JSON into a Java POJO. I'm hitting a 3rd party RESTful web service and this is an example of the JSON I'm getting back:
{
"response": {
"job":{
"eta":-1,
"status":"approved",
"mt":1,
"lc_tgt":"fr",
"body_src":"Please translated me.",
"body_tgt":"S'il vous plaît traduire moi.",
"unit_count":3,
"tier":"machine",
"credits":0,
"ctime":"2013-02-07 14:56:12.391963",
"lc_src":"en",
"slug":"0",
"job_id":"NULL"
}
},
"opstat":"ok"
}
The POJO I'm trying to map this into is:
public class Job {
// correlates to "eta"
private int eta;
// correlates to "body_src"
private String sourceBody;
// correlates to "ctime"
private java.util.Date creationTimestamp;
// Getters and setters for all 3 properties
}
When I run the following code, I don't get any exceptions, but the print statement just prints "null":
// Hit the 3rd party service and get the JSON (example above).
JSONObject json = hitRestfulWebService();
Gson gson = new Gson();
// json.toString = "{response":{"job":{ ..."
Job job = gson.fromJson(json.toString(), Job.class);
System.out.println(job.getSourceBody());
My only guess is that GSON can't figure out how to map the 3 JSON fields to my 3 Job properties. Can someone help me figure out what this mapping needs to be? Thanks in advance.
You can use annotations to define, which json field gets mapped to which object member, e.g.:
class SomeClass
{
#SerializedName("body-src")
String myString1;
#SerializedName("header-src")
String myString2;
...
public class Response{
private Job job;
//generate setter and getter
}
public class Job {
// correlates to "eta"
private int eta;
// correlates to "body_src"
private String sourceBody;
// correlates to "ctime"
private java.util.Date creationTimestamp;
// Getters and setters for all 3 properties
}
now in Gson
JSONObject json = hitRestfulWebService();
Gson gson = new Gson();
// json.toString = "{response":{"job":{ ..."
Job job = gson.fromJson(json.toString(), Response.class);
use not response but response.job
not
{ "response": {..
use
{ "eva": ..
this may help;
String a = "{\"response\": {\"job\":{\"eta\":-1,\"status\":\"approved\",\"mt\":1,\"lc_tgt\":\"fr\",\"body_src\":\"Please translated me.\",\"body_tgt\":\"S'il vous plaît traduire moi.\",\"unit_count\":3,\"tier\":\"machine\",\"credits\":0,\"ctime\":\"2013-02-07 14:56:12.391963\",\"lc_src\":\"en\",\"slug\":\"0\",\"job_id\":\"NULL\"}},\"opstat\":\"ok\"}";
Job j = I.gson().fromJson(
((JsonObject) ((JsonObject) new JsonParser().parse(a)).get("response")).get("job"), Job.class);
System.out.println(j.getEta());

Categories