Parse JSON Data using POJO, Where key name is numeric - java

I'm trying to parse a special JSON data using Wrapper class, special means a JSON which have numeric keys like below :
{
"date":"2018-11-01",
"hours":"01-Nov 08:00",
"1011":"837.7500",
"1022":"99.92596979567664",
"1010":"3.198083",
"1021":"5",
"1019":"1171.000",
"1018":"3.578371",
"1017":"30.46989",
"1016":"0.0001931423",
"1015":"6749",
"1014":"0.161805",
"1013":"0.001678397",
"1012":"1.406077"
}
I know how to parse JSON data using POJO, But in this case java is not accepting the numeric as Keys.
Wrapper/POJO Class
I don't want to go with JSON object based parsing. Is Anyone have any idea about it?

The Gson library has SerializedName functionality in which it parses the corresponding value of the key defined in SerializeName's parameter. Things will be tougher if your key is a pure integer since Java disallows it as variable name, in this case SerializeName will save you from that headache and it makes your code way more maintainable.
Example usage :
#SerializedName("1011") double lat;
#SerializedName("1022") double lng;

Try Gson for create wrapper class
http://www.jsonschema2pojo.org/
public class Example {
#SerializedName("date")
#Expose
private String date;
#SerializedName("hours")
#Expose
private String hours;
#SerializedName("1011")
#Expose
private String _1011;
#SerializedName("1022")
#Expose
private String _1022;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getHours() {
return hours;
}
public void setHours(String hours) {
this.hours = hours;
}
public String get1011() {
return _1011;
}
public void set1011(String _1011) {
this._1011 = _1011;
}
public String get1022() {
return _1022;
}
public void set1022(String _1022) {
this._1022 = _1022;
}

Have a look at this code ,hope it works for you
JSONObject jsonObjectData = jsonObject1.getJSONObject("yourObject");
Iterator iterator = jsonObjectData.keys();
while (iterator.hasNext()) {
YourClass yourClass = new YourClass();
String key = (String) iterator.next();
yourClass.setKey(key);
yourClass.setVajue(jsonObjectData.getString(key));
yourList.add(yourClass);
}

Related

Java 14 records with org.json

I wanted to make new JSON object with org.json library, but I have noticed there is a problem with Java 14 records.
When I call
String json = new JSONObject(new Order("", "Albert", "GOOGL", "SELL", 97.9, 90L)).toString();
the fields are null.
I suppose it is because java record doesn't use old getters like getXYZ?
Is there a simple work around? I mean without using different library.
Or maybe my assumptions are incorrect.
public record Order(
String id,
String userId,
String securityId,
String type,
Double price,
Long quantity
) {
}
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20220320</version>
</dependency>
If you don't want to use other libraries like Jackson or Gson (it will be a much better solution in my opinion) you could write your own converter:
public final class JsonConverter {
private JsonConverter() {
}
#SneakyThrows
public static String toJSON(Object object) {
Class<?> c = object.getClass();
JSONObject jsonObject = new JSONObject();
for (Field field : c.getDeclaredFields()) {
field.setAccessible(true);
String name = field.getName();
Object value = field.get(object);
jsonObject.put(name, value);
}
return jsonObject.toString();
}
}
You could use it like:
public static void main(String[] args) {
Order order = new Order("", "Albert", "GOOGL", "SELL", 97.9, 90L);
System.out.println(order);
JSONObject jsonObject = new JSONObject(order);
System.out.println(jsonObject.toString());
System.out.println(JsonConverter.toJSON(order));
}
Output:
OrderRecord[id=, userId=Albert, securityId=GOOGL, type=SELL, price=97.9, quantity=90]
{}
{"quantity":90,"price":97.9,"securityId":"GOOGL","id":"","type":"SELL","userId":"Albert"}
It is a real workaround. However, it uses exactly org.json.
According to documentation JSONObject(Object bean) constructor
construct a JSONObject from an Object using bean getters.
So, yes as you noticed it expects getter to be in format getFieldName(), but in records getters are named differently.
For, example getter for filed price would be price(), not getPrice().
One possible solution is to add getters in record class, like this :
public record Order(
String id,
String userId,
String securityId,
String type,
Double price,
Long quantity
) {
public Double getPrice() { // Compliant
return price;
}
public String getId() { // Compliant
return id;
}
public String getSecurityId() { // Compliant
return securityId;
}
public String getType() { // Compliant
return type;
}
public Long getQuantity() { // Compliant
return quantity;
}
}
You should see output like this :

Jackson: Serializing Map<Object, BigDecimal> yields undesired object reference

Suppose I am trying to serialize the following with Jackson:
public class Investment implements Serializable{
private String shortName;
private MutualFund mutualFund;
public String getShortName() {
return shortName;
}
public void setShortName(String shortName) {
this.shortName = shortName;
}
public MutualFund getMutualFund() {
return mutualFund;
}
public void setMutualFund(MutualFund mutualFund) {
this.mutualFund = mutualFund;
}
}
That in turn refers to:
public class MutualFund implements Serializable{
private BigDecimal expenseRatio;
private Map<Investment, BigDecimal> underlyingInvestments;
public BigDecimal getExpenseRatio() {
return BigDecimalHelper.guard(expenseRatio);
}
public void setExpenseRatio(BigDecimal expenseRatio) {
this.expenseRatio = expenseRatio;
}
public Map<Investment, BigDecimal> getUnderlyingInvestments() {
return underlyingInvestments;
}
public void setUnderlyingInvestments(Map<Investment, BigDecimal>
underlyingFunds) {
this.underlyingInvestments = underlyingFunds;
}
}
When I try to serialize this with Jackson, everything else is fine except that I end up with an Investment object reference instead of the string with attributes like I was expecting:
"underlyingInvestments":{"com.financial.detail.Investment#5d465e4b":1}}
I've tried to fashion some custom serializers, but without success as I always get an object reference for the nested Investment(s). So, I have a two part question:
Can this problem be addressed simply with Jackson annotations?
If I have to build a custom serializer, could someone kindly point me in the right direction on how to best
approach this issue given the nested nature of this (e.g. an Investment could contain a Mutual Fund, which in turn has an Investment with a Mutual Fund...)
The problem is that you are using the object Investment as keys of a Map, so the question here is, what keys do you expect the json to have? Json keys cand only be strings so the mapper is executing the toString() method of the Investment class. If you know what that key should be, then you can implement the method, like this:
public class Investment implements Serializable {
private String shortName;
private MutualFund mutualFund;
// ...
#Override
public String toString() {
return shortName;
}
}
This will create a json object like this:
{
"expenseRatio": 1,
"underlyingInvestments": {
"shortName": 10
}
}
Also, as #chrylis-cautiouslyoptimistic suggested, another option is to use #JsonValue to indicate which method to use when serializing, like this:
public class Investment implements Serializable{
private String shortName;
private MutualFund mutualFund;
#JsonValue
public String getShortName() {
return shortName;
}
// ...
}

How to convert JSON object using GSON in Java?

Here is the JSON string return from API:
{"id":1,"bps_id":"C199","summary":{"as_of_date":"2017-06-20","bp_earned":0,"bp_balance":"199400","bp_redeemed":"600"},"bps_message":{"eng":"mobile testing message","chi":"mobile testing message chi"},"bps_image":"https:\/\/mydomain.com\/images\/eng\/promotion\/C199_MH.gif","error_message":{"eng":"","chi":""},"error_flags":""}
And I have created an object for this:
public class SummaryResponse {
String bps_id;
String bps_image;
String bps_message;
String as_of_date;
String bp_earned;
String bp_redeemed;
String bp_balance;
public String getBps_image() {
return bps_image;
}
public LangResponse getBps_message() {
return bps_message;
}
public String getAs_of_date() {
return as_of_date;
}
public String getBp_earned() {
return bp_earned;
}
public String getBp_redeemed() {
return bp_redeemed;
}
public String getBp_balance() {
return bp_balance;
}
}
It does not convert as expert, as there is some JSON object inside the string, how to convert that as well? Thanks for helping.
You can create like this,
public class SummaryResponse {
public String id;
public String bps_id;
public Summary summary;
public Message bps_message;
public String bps_image;
public Message error_message;
public String error_flags;
class Summary {
public String as_of_date;
public int bp_earned;
public String bp_balance;
public String bp_redeemed;
}
class Message {
public String eng;
public String chi;
}
}
you can call like this.
SummaryResponse summaryResponse = new Gson().fromJson([Your Json], SummaryResponse.class);
This a quick simple way to parse an array of Objects and also a single object it works for me when I am parsing json.
I believe it will only work as long as the json object is well formatted. I haven't experimented with a ill-formatted json object but that is because the api it request from was build by me, so I haven't had to worry about that
Gson gson = new Gson();
SummaryResponse[] data = gson.fromJson(jsonObj, SummaryResponse[].class);

Convert java object in JSON

I'm trying to convert a simple java object in JSON. I'm using google Gson library and it works, but I want a complete JSON object in this form:
{"Studente":[{ "nome":"John", "cognome":"Doe","matricola":"0512","dataNascita":"14/10/1991"}]}
This is my class:
public class Studente {
private String nome;
private String cognome;
private String matricola;
private String dataNascita;
public Studente(){
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getCognome() {
return cognome;
}
public void setCognome(String cognome) {
this.cognome = cognome;
}
public String getMatricola() {
return matricola;
}
public void setMatricola(String matricola) {
this.matricola = matricola;
}
public String getDataNascita() {
return dataNascita;
}
public void setDataNascita(String dataNascita) {
this.dataNascita = dataNascita;
}
}
This is tester:
Studente x = new Studente();
x.setCognome("Doe");
x.setNome("Jhon");
x.setMatricola("0512");
x.setDataNascita("14/10/1991");
Gson gson = new Gson();
String toJson = gson.toJson(x, Studente.class);
System.out.println("ToJSON "+toJson);
I have this in toJson: {"nome":"Jhon","cognome":"Doe","matricola":"0512","dataNascita":"14/10/1991"}
The Json that you are trying to achieve is not the representation of a single Studente object, it is the representation of an object containing a list of Studente objects, that has a single entry.
So, you would need to create that extra object that contains the list of Studente objects, add the one instance to the list, and then serialize the object containing the list.
There's one minor issue, though. You are essentially asking for the wrapper object's list to have a property name that starts with a capital letter. This can be done, but breaks Java coding conventions.
It is best to write a wrapper for Students list. like this:
import java.util.ArrayList;
public class StudentWrapper {
private ArrayList<Studente> studente;
public StudentWrapper() {
studente = new ArrayList<Studente>();
}
public void addStudent(Studente s){
studente.add(s);
}
}
Code to convert to JSON :
Studente x=new Studente();
x.setCognome("Doe");
x.setNome("Jhon");
x.setMatricola("0512");
x.setDataNascita("14/10/1991");
Gson gson=new Gson();
StudentWrapper studentWrapper = new StudentWrapper();
studentWrapper.addStudent(x);
String toJson=gson.toJson(studentWrapper, StudentWrapper.class);
System.out.println("ToJSON "+toJson);
The output will be like this. The way you want it.
ToJSON {"studente":[{"nome":"Jhon","cognome":"Doe","matricola":"0512","dataNascita":"14/10/1991"}]}

Convert Java complex object to Json

I need to convert the following Class:
package comS309.traxz.data;
import java.util.Collection;
import org.json.JSONException;
import org.json.JSONObject;
public class ExerciseSession {
public String DateCreated;
public String TotalTime;
public String CaloriesBurned;
public String AvgSpeed;
public String SessionName;
public String Distance;
public String SessionType;
public String UserId;
public Collection<LatLon> LatLons;
}
Where LatLon is as follows:
public class LatLon {
public String LatLonId;
public String Latitude;
public String Longitude;
public String ExerciseSessionId;
public String LLAveSpeed;
public String Distance;
}
So the Class ExerciseSession has a collection of LatLon objects. Now I need to convert The ExerciseSession Class into a Json format from java and send it to my server.
I am doing this on the android OS, if that matters.
My current solution is this:
JSONObject ExerciseSessionJSOBJ = new JSONObject();
ExerciseSessionJSOBJ.put("DateCreated", this.DateCreated);
ExerciseSessionJSOBJ.put("TotalTime", this.TotalTime);
ExerciseSessionJSOBJ.put("CaloriesBurned", this.CaloriesBurned);
ExerciseSessionJSOBJ.put("AvgSpeed", this.AvgSpeed);
ExerciseSessionJSOBJ.put("SessionName", this.SessionName);
ExerciseSessionJSOBJ.put("Distance", this.Distance);
ExerciseSessionJSOBJ.put("SessionType", this.SessionType);
ExerciseSessionJSOBJ.put("UserId", this.UserId);
//add the collection
for(LatLon l: LatLons)
{
ExerciseSessionJSOBJ.accumulate("LatLons", l);
}
I am not sure this is valid.. I am a novice with Json and need help.
Thanks in advance for the help!
This is very easy to do using Google's GSON library. Here's an example use:
Gson gson = new Gson();
String jsonRepresentation = gson.toJson(myComplexObject);
And to get the object back:
Gson gson = new Gson();
MyComplexObject myComplexObject = gson.fromJson(jsonRepresentation, MyComplexObject.class);
http://code.google.com/p/google-gson/
You can also serialize the object using flexjson: http://flexjson.sourceforge.net/
I think using the accumulate is correct. See: http://www.json.org/javadoc/org/json/JSONObject.html#accumulate(java.lang.String,%20java.lang.Object)
But you need to create a JSONObject for each LatLon as you do for the ExerciseSession object.
Then, the following line is wrong:
ExerciseSessionJSOBJ.accumulate("LatLons", l);
"l" must be transformed.
I would really suggest you avoid using JSONObject to convert between Strings and Java objects. It will probably claim your sanity if you have to do too much of it. As an alternative, I'm a big fan of Jackson, which does what you describe in a really pleasant and simple way.
As a basic example,
public static class LatLon {
public final String LatLonId;
public final String Latitude;
public final String Longitude;
public final String ExerciseSessionId;
public final String LLAveSpeed;
public final String Distance;
#JsonCreator
public LatLon(#JsonProperty("distance") String distance,
#JsonProperty("exerciseSessionId") String exerciseSessionId,
#JsonProperty("latitude") String latitude,
#JsonProperty("latLonId") String latLonId,
#JsonProperty("LLAveSpeed") String LLAveSpeed,
#JsonProperty("longitude") String longitude) {
this.Distance = distance;
this.ExerciseSessionId = exerciseSessionId;
this.Latitude = latitude;
this.LatLonId = latLonId;
this.LLAveSpeed = LLAveSpeed;
this.Longitude = longitude;
}
public static void something() {
ObjectMapper mapper = new ObjectMapper();
String json = "{\"LLAveSpeed\":\"123\",\"Distance\":\"123\","
+ "\"ExerciseSessionId\":\"123\",\"LatLonId\":\"123\","
+ "\"Latitude\":\"123\",\"Longitude\":\"123\"}";
try {
//turn the json string into a LatLon object.
LatLon latLon = mapper.readValue(json, LatLon.class);
//turn the latLon object into a new JSON string
String newJson = mapper.writeValueAsString(latLon);
//confirm that the strings are equal
Log.w("JacksonDemo", "Are they equal? " + json.equals(newJson));
}
catch (IOException e) {
e.printStackTrace();
}
}
}
This outputs Are they equal? true.
So you use readValue() to convert json to a Java object, writeValueAsString() to write an object back into json. #JsonCreator marks the constructor Jackson should use to convert betwee json and Java. #JsonProperty("jsonKeyName") marks the name of a variable in the json string and the Java variable it should map to.
This is a little confusing at first but saves a lot of time once you figure it out. Let me know if anything is unclear.

Categories

Resources