Reputation: 651
I have stayed with the problem for more than 3 days of research but cant find any solvable solution. My android project makes a request to my gcloud functions and the function returns a string response with a String format:
[{"response": [{"Commission": 50, "Price": 0.5, "Quantity": "20"}, {"Commission": 50, "Quantity": 20, "Price": 1}, {"Quantity": 20, "Price": 10, "Commission": 50}], "code": 200}]
I was able to convert the string to JSON and retrieve the value of the "response" key.
try {
//convertion of response to json to fetch value
JSONObject jsonObj = new JSONObject("[{"response": [{"Commission": 50, "Price": 0.5, "Quantity": "20"}, {"Commission": 50, "Quantity": 20, "Price": 1}, {"Quantity": 20, "Price": 10, "Commission": 50}], "code": 200}]");
String code = jsonObj.getString("code");
final String Cod = code;
if (Cod.equals("200")){
String availableInv = jsonObj.getString("response");
availableInv = availableInv.replace("[", "");
availableInv = availableInv.replace("]", "");
String strng[] = availableInv.split("},");
for (String val:strng) {
int valLength = val.length();
if(!val.substring(valLength-1, valLength).contentEquals("}")) {
val +="}";
}
System.out.println(">>>>>>=====================response==========="+val);
JSONObject jsonObjInv = new JSONObject(val);
float price = Float.valueOf(jsonObjInv.getString("Price"));
float comission = Float.valueOf(jsonObjInv.getString("Commission"));
float quantity = Float.valueOf(jsonObjInv.getString("Quantity"));
myDataset.add(new InvestmentsModel(price,comission, quantity));
}
}
}
Now i want to be able to iterate through the list of the JSON object and fetch the keys and values. When i run my solution i get the following error:
2020-03-24 16:17:55.235 4959-5006/com.example.SMS E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
Process: com.example.SMS, PID: 4959
java.util.regex.PatternSyntaxException: Syntax error in regexp pattern near index 1
},
^
at java.util.regex.Pattern.compileImpl(Native Method)
at java.util.regex.Pattern.compile(Pattern.java:1340)
at java.util.regex.Pattern.<init>(Pattern.java:1324)
at java.util.regex.Pattern.compile(Pattern.java:946)
at java.lang.String.split(String.java:2384)
at java.lang.String.split(String.java:2426)
at com.example.SMS.Fragment.investEarnFrag_1$5.onResponse(investEarnFrag_1.java:251)
at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:504)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
Upvotes: 0
Views: 412
Reputation: 136
Seems that you find your answer in the comments. However, I think there is some point which is worth to emphasize here.
First of all, since you already decided to serialize your raw json
response to a java
object, which is JSONObject
in this case, there is no point to parse the rest of the string anymore. You should stick with one of the methodologies to keep it consistent. So, in this case the methodology should be either parsing the whole json
string or using org.json
features. In my personal opinion, you should keep using the org.json
.
Using org.json
The response you shared is in form of array
/list
of object
.
[{"response": [{"Commission": 50, "Price": 0.5, "Quantity": "20"}, {"Commission": 50, "Quantity": 20, "Price": 1}, {"Quantity": 20, "Price": 10, "Commission": 50}], "code": 200}]
Since we have array
of objects
, we should use JSONArray
to keep our json
in.
JSONArray jsonArray = new JSONArray("[{\"response\": [{\"Commission\": 50, \"Price\": 0.5, \"Quantity\": \"20\"}, {\"Commission\": 50, \"Quantity\": 20, \"Price\": 1}, {\"Quantity\": 20, \"Price\": 10, \"Commission\": 50}], \"code\": 200}]");
// just to exemplify we get the first element, this should be depending on the business logic
JSONObject jsonObj = (JSONObject) jsonArray.get(0);
Now, we have the inner object in our jsonObj
variable, which is:
{
"response": [
{
"Commission": 50,
"Price": 0.5,
"Quantity": "20"
},
{
"Commission": 50,
"Quantity": 20,
"Price": 1
},
{
"Quantity": 20,
"Price": 10,
"Commission": 50
}
],
"code": 200
}
So, we can easily get on key response
which will be againg an array
of object
. We can easily iterate on it.
Note that in
json
all keys arestring
while values can bestring
,numeric
,booelan
andobject
. For instance, status can be parsed as integer.
try {
//convertion of response to json to fetch value
JSONArray jsonArray = new JSONArray("[{\"response\": [{\"Commission\": 50, \"Price\": 0.5, \"Quantity\": \"20\"}, {\"Commission\": 50, \"Quantity\": 20, \"Price\": 1}, {\"Quantity\": 20, \"Price\": 10, \"Commission\": 50}], \"code\": 200}]");
JSONObject jsonObj = (JSONObject) jsonArray.get(0);
int code = jsonObj.getInt("code");
List<InvestmentsModel> myDataset = new ArrayList<>();
if (code == 200){
JSONArray availableInv = jsonObj.getJSONArray("response");
for (Object val: availableInv) {
JSONObject value = (JSONObject) val;
float price = value.getFloat("Price");
float comission = value.getFloat("Commission");
float quantity = value.getFloat("Quantity");
myDataset.add(new InvestmentsModel(price,comission, quantity));
}
}
} catch (Exception e ) {
// todo handle exception
}
This can be a more naive answer to your question than parsing the raw response.
Taking one step further
It seems that we already have model class for InvestmentsModel
. The more elegant approach is to keep things in their own contexts and to create for pojo
s for responses.
Assumed we have such InvestmentsModel
:
import com.fasterxml.jackson.annotation.JsonProperty;
public class InvestmentsModel {
@JsonProperty("Price")
private float price;
@JsonProperty("Commission")
private float comission;
@JsonProperty("Quantity")
private float quantity;
public InvestmentsModel() {
}
public InvestmentsModel(float price, float comission, float quantity) {
this.price = price;
this.comission = comission;
this.quantity = quantity;
}
public InvestmentsModel price(float price) {
this.price = price;
return this;
}
public InvestmentsModel comission(float comission) {
this.comission = comission;
return this;
}
public InvestmentsModel quantity(float quantity) {
this.quantity = quantity;
return this;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public float getComission() {
return comission;
}
public void setComission(float comission) {
this.comission = comission;
}
public float getQuantity() {
return quantity;
}
public void setQuantity(float quantity) {
this.quantity = quantity;
}
@Override
public String toString() {
return "[price -> " + this.price + ", comission -> " + this.comission + ", quantity -> " + this.quantity + "]";
}
}
For the response structure, we have:
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
public class GetInvestmentsResponseModel {
@JsonProperty("response")
private List<InvestmentsModel> response;
@JsonProperty("code")
private int code;
public GetInvestmentsResponseModel() {
}
public GetInvestmentsResponseModel(List<InvestmentsModel> response, int code) {
this.response = response;
this.code = code;
}
public GetInvestmentsResponseModel response(List<InvestmentsModel> response) {
this.response = response;
return this;
}
public GetInvestmentsResponseModel code(int code) {
this.code = code;
return this;
}
public List<InvestmentsModel> getResponse() {
return response;
}
public void setResponse(List<InvestmentsModel> response) {
this.response = response;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
And then code becomes:
final String rawResponse = "[{\"response\": [{\"Commission\": 50, \"Price\": 0.5, \"Quantity\": \"20\"}, {\"Commission\": 50, \"Quantity\": 20, \"Price\": 1}, {\"Quantity\": 20, \"Price\": 10, \"Commission\": 50}], \"code\": 200}]";
ObjectMapper mapper = new ObjectMapper();
try {
GetInvestmentsResponseModel[] responseObjects = mapper.readValue(rawResponse, GetInvestmentsResponseModel[].class);
GetInvestmentsResponseModel responseObject = responseObjects[0];
if(responseObject.getCode() == 200) {
List<InvestmentsModel> investmentsModels = responseObject.getResponse();
System.out.println(investmentsModels);
}
} catch (JsonProcessingException e) {
// handle JsonProcessingException
}
Outputs as just as in the InvestmentsModel
's toString()
:
[[price -> 0.5, comission -> 50.0, quantity -> 20.0], [price -> 1.0, comission -> 50.0, quantity -> 20.0], [price -> 10.0, comission -> 50.0, quantity -> 20.0]]
Take one more step further
The final suggestion is to use swagger to both keep track of the api and get rid of the most of the boilerplate code. It can be used both clients and servers, and keeps APIs documented and clean. Please check this out for swagger.
Upvotes: 1