如何使用 Java 将包含 JSON 对象的字符串转换为实际的 JSON

How to convert String containing JSON object to actual JSON using Java

我已经研究了 3 天多,但找不到任何可解决的解决方案。我的 android 项目向我的 gcloud 函数发出请求,函数 returns 一个字符串格式的字符串响应:

[{"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.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)

看来您在评论中找到了答案。不过,我觉得这里有一点值得强调

首先,由于您已经决定将原始 json 响应序列化为 java 对象,在本例中为 JSONObject,因此没有必要解析其余的字符串了。您应该坚持使用其中一种方法以保持一致。因此,在这种情况下,方法应该是解析整个 json 字符串或使用 org.json 特征。在我个人看来,你应该继续使用 org.json.

使用org.json

您分享的回复格式为 array/listobject

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

因为我们有 arrayobjects,我们应该使用 JSONArray 来保持我们的 json

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 键,这将是 objectarray。我们可以很容易地对其进行迭代。

Note that in json all keys are string while values can be string, numeric, booelan and object. 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
}  

与解析原始响应相比,这可能是对您问题的更幼稚的回答。

更进一步

我们似乎已经有了 InvestmentsModel 的模型 class。更优雅的方法是将事物保留在它们自己的上下文中,并为 pojo 创建响应。

假设我们有这样的 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
        }

输出与 InvestmentsModeltoString() 一样:

[[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]]

再进一步

最后的建议是使用 swagger 来跟踪 api 并摆脱大部分样板代码。它可用于客户端和服务器,并保持 API 文档化和清洁。请检查 this 是否招摇。