Как преобразовать строку, содержащую JSON объект, в фактический JSON, используя Java - PullRequest
0 голосов
/ 24 марта 2020

Я оставался с проблемой в течение более 3 дней исследований, но не могу найти никакого решения. Мой android проект выполняет запрос к моим функциям gcloud, и функция возвращает строковый ответ в формате String:

[{"response": [{"Commission": 50, "Price": 0.5, "Quantity": "20"}, {"Commission": 50, "Quantity": 20, "Price": 1}, {"Quantity": 20, "Price": 10, "Commission": 50}], "code": 200}]

Мне удалось преобразовать строку в JSON и получить значение ключ "response".

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));
                    }
                }
            }

Теперь я хочу иметь возможность перебирать список объекта JSON и извлекать ключи и значения. Когда я запускаю свое решение, я получаю следующую ошибку:

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)

1 Ответ

1 голос
/ 24 марта 2020

Похоже, вы найдете свой ответ в комментариях. Тем не менее, я думаю, что есть некоторый момент, который стоит подчеркнуть здесь .

Прежде всего, поскольку вы уже решили сериализовать свой необработанный json ответ на java объект, в этом случае JSONObject, нет смысла больше разбирать остальную часть строки. Вы должны придерживаться одной из методологий, чтобы она была последовательной. Таким образом, в этом случае методология должна либо анализировать всю строку json, либо использовать org.json функции. По моему личному мнению, вы должны продолжать использовать org.json.

Использование org.json

Ответ, которым вы поделились, имеет вид array / list из object.

[{"response": [{"Commission": 50, "Price": 0.5, "Quantity": "20"}, {"Commission": 50, "Quantity": 20, "Price": 1}, {"Quantity": 20, "Price": 10, "Commission": 50}], "code": 200}]

Так как у нас array из objects, мы должны использовать JSONArray, чтобы сохранить 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);

сейчас у нас есть внутренний объект в нашей переменной jsonObj:

{
  "response": [
    {
      "Commission": 50, 
      "Price": 0.5, 
      "Quantity": "20"
    }, 
    {
      "Commission": 50, 
      "Quantity": 20, 
      "Price": 1
    }, 
    {
      "Quantity": 20, 
      "Price": 10, 
      "Commission": 50
    }
  ], 
  "code": 200
}

Итак, мы можем легко получить ключ response, который будет array из object. Мы можем легко повторить его.

Обратите внимание, что в json все ключи string, а значения могут быть string, numeric, booelan и object. Например, статус может быть проанализирован как целое число.

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
}  

Это может быть более наивный ответ на ваш вопрос, чем разбор необработанного ответа.

Выполнение одного шага далее

Похоже, у нас уже есть класс модели для InvestmentsModel. Более элегантный подход состоит в том, чтобы держать вещи в их собственных контекстах и ​​создавать для pojo s для ответов.

Предполагается, что у нас есть такие 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 + "]";
    }
}

Для структуры ответа , у нас есть:

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;
    }
}

И тогда код становится:

        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
        }

Выходы, как и в InvestmentsModel 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]]

Сделайте еще один шаг вперед

Последнее предложение - использовать чванство для отслеживания API и избавления от большей части стандартного кода. Он может использоваться как клиентами, так и серверами, и поддерживает документирование и чистоту API. Пожалуйста, проверьте это на чванство.

...