OkHttp如何获取Json字符串?

78

解决方案: 这是我的错误。

正确的方式是使用response.body().string()而不是response.body.toString()

我正在使用Jetty servlet,URL是http://172.16.10.126:8789/test/path/jsonpage,每次请求此URL时它都会返回

{"employees":[
    {"firstName":"John", "lastName":"Doe"}, 
    {"firstName":"Anna", "lastName":"Smith"},
    {"firstName":"Peter", "lastName":"Jones"}
]}

当在浏览器中输入URL时,它会出现,但是当我使用Okhttp请求时,它显示的是一种内存地址,而不是JSON字符串。

TestActivity﹕ com.squareup.okhttp.internal.http.RealResponseBody@537a7f84

我使用的Okhttp代码:

OkHttpClient client = new OkHttpClient();

String run(String url) throws IOException {
  Request request = new Request.Builder()
      .url(url)
      .build();

  Response response = client.newCall(request).execute();
  return response.body().string();
}

有人可以帮忙吗?


它从char字节和字符集构建String对象。 - Nikola Despotoski
4
谢谢!这是我的错。我把 response.body().string() 替换成了 response.body().toString()... - Haifeng Zhang
2
@haifzhan 感谢您澄清使用 response.body().string() 而不是 response.body().toString() 的用法。 - user3144836
6个回答

138
try {
    OkHttpClient client = new OkHttpClient();
    Request request = new Request.Builder()
        .url(urls[0])
        .build();
    Response responses = null;

    try {
        responses = client.newCall(request).execute();
    } catch (IOException e) {
        e.printStackTrace();
    }
    String jsonData = responses.body().string();
    JSONObject Jobject = new JSONObject(jsonData);
    JSONArray Jarray = Jobject.getJSONArray("employees");

    for (int i = 0; i < Jarray.length(); i++) {
        JSONObject object     = Jarray.getJSONObject(i);
    }
}

示例添加到您的列中:

JCol employees  = new employees();
colums.Setid(object.getInt("firstName"));
columnlist.add(lastName);           

8
我现在遇到了这个异常:org.json.JSONException: Value okhttp3.internal.http.RealResponseBody@aeb56f3 of type java.lang.String cannot be converted to JSONObject - Gokul NC
23
很容易犯的错误是混淆.string().toString() - Zapnologica
10
请说明您获取对象的位置,例如 JSONObject。请同时包括导入(imports)内容。 - Diego Alves
我正在尝试使用Okhttp(3.x.x)进行简单请求,这是请求的基础吗? - RoCkDevstack
responses.body().string() can be called just one time <br/> use this code directlty : //String jsonData = responses.body().string(); JSONObject Jobject = new JSONObject(responses.body().string()); - Chakib Temal
我们如何将多个字段作为对象获取?例如,我们能否获取像员工这样的另一个字段? - Manodhya Opallage

27

我也遇到了同样的问题

使用这段代码:

// notice string() call
String resStr = response.body().string();    
JSONObject json = new JSONObject(resStr);

肯定有效


非常感谢!有趣的是,文档中没有关于string()方法的信息。但它确实有效。 - Leo DroidCoder
非常感谢您的回答。这对我帮助很大!奇怪的是我在互联网上找不到其他相关信息! - apmartin1991
非常感谢。string() 看起来很奇怪,但它的效果非常好! - Ronak Gadhia
对于包含“data”和“error”对象的OKHttp3 GraphQL响应,这也适用。 - Paixols
添加toString()不是多余的吗?你只需要使用response.body().string()就可以了,它会返回一个字符串。 - portfoliobuilder

24

就我的代码观察,如果从响应中获取了body的值后,它就变成了空白。

String str = response.body().string();  // {response:[]}

String str1  = response.body().string();  // BLANK

我认为在从 body 获取值一次之后,它就变为空了。

建议:将其存储在字符串中,可以多次使用。


1
非常感谢。我尝试解决这个问题已经有一段时间了,但以上的回答都没有真正帮到我,因为我一开始是先记录整个主体,然后再试图获取字符串,这才是问题所在。 - Saad Ismail
那是正确的。多么荒谬的情况。 - undefined

9

我希望您已经成功地从JSON字符串中获取了JSON数据。

我认为这将对您有所帮助。

try {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
    .url(urls[0])
    .build();
Response responses = null;

try {
    responses = client.newCall(request).execute();
} catch (IOException e) {
    e.printStackTrace();
}   

String jsonData = responses.body().string();

JSONObject Jobject = new JSONObject(jsonData);
JSONArray Jarray = Jobject.getJSONArray("employees");

//define the strings that will temporary store the data
String fname,lname;

//get the length of the json array
int limit = Jarray.length()

//datastore array of size limit
String dataStore[] = new String[limit];

for (int i = 0; i < limit; i++) {
    JSONObject object     = Jarray.getJSONObject(i);

    fname = object.getString("firstName");
    lname = object.getString("lastName");

    Log.d("JSON DATA", fname + " ## " + lname);

    //store the data into the array
    dataStore[i] = fname + " ## " + lname;
}

//prove that the data was stored in the array      
 for (String content ; dataStore ) {
        Log.d("ARRAY CONTENT", content);
    }

请记得使用AsyncTask或SyncAdapter(IntentService),以避免出现NetworkOnMainThreadException的情况。

同时,在你的build.gradle文件中导入okhttp库。

compile 'com.squareup.okhttp:okhttp:2.4.0'


我能和这个一起使用 DownloadManager 吗? - RoCkDevstack
如果你注意到了,一旦你下载了一个文件,状态栏上会出现一个闪烁的白色向下箭头,表示你已经下载了某些东西。这是由DownloadManager处理的。 - RoCkDevstack

3
以下代码是使用GET方法和okHTTP库获取来自在线服务器的数据的代码,用于Android Kotlin...
Log.e("Main", response.body!!.string())
在上述代码中,!!是您可以使用它从响应正文中获取JSON的东西。
val client = OkHttpClient()
            val request: Request = Request.Builder()
                .get()
                .url("http://172.16.10.126:8789/test/path/jsonpage")
                .addHeader("", "")
                .addHeader("", "")
                .build()
            client.newCall(request).enqueue(object : Callback {
                override fun onFailure(call: Call, e: IOException) {
                    // Handle this
                    Log.e("Main","Try again latter!!!")
                }

                override fun onResponse(call: Call, response: Response) {
                    // Handle this
                    Log.e("Main",response.body!!.string())
                }
            })

1

我想再添加一点观察结果。您只能调用.string()方法一次。如果尝试两次调用,将会抛出不合法的状态异常。


1
你的回答可以通过提供额外的支持信息来改善。请[编辑]以添加进一步细节,例如引用或文档,以便他人可以确认您的答案是正确的。您可以在帮助中心中找到更多有关如何撰写优秀答案的信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接