如何从JSONObject中删除nameValuePairs键?

h43kikqp  于 2022-12-01  发布在  其他
关注(0)|答案(8)|浏览(197)

我正在开发一个Android项目,它需要一个JSONObject作为POST请求的主体。在输入JSON的键和值之后,我得到了下面这行代码:

{
    "xxxx":"zzzzzzz",
    "yyyy":"uuuuuuu"
}

但是服务器得到了以下信息:

{
    "name_value_pairs": {
                        "xxxx":"zzzzzzz",
                        "yyyy":"uuuuuuu"
    }
}

我已经尝试了JSONStringer,但它没有真正的帮助,因为请求的Content-Typeapplication/json

更新

我并没有试图构造一个JSONObject,因为它已经通过使用下面的代码行(与@osayilgan给出的代码相同)完成了:

JSONObject jsonRequest = new JSONObject();
jsonRequest.put("xxxx", "zzzzzzz");
jsonRequest.put("yyyy", "uuuuuuu");

这里没有问题。下面描述的接口是用来与服务器通信的。

public interface MyService {
    @Headers({"Content-type: application/json",
              "Accept: */*"})
    @POST("/test")
    void testFunction(@Body JSONObject jsonObject, Callback<Response> callback);
}

服务器收到的请求是第二个JSON作为Body,这令人失望。我注意到关键字name_value_pairs被自动添加到对象中。
有人知道我该怎么解决这个问题吗?

ecbunoof

ecbunoof1#

版本

默认情况下,Retrofit使用GSON将HTTP主体转换为JSON,或者将JSON转换为HTTP主体。使用@Body注解指定的对象将被传递到GSON进行序列化,这基本上将JAVA对象转换为JSON表示。此JSON表示将成为HTTP请求主体。
JSONObject将所有键-值Map存储在一个名为nameValuePairs的成员变量中。

public class JSONObject {
    ...
    private final Map<String, Object> nameValuePairs;
    ...
}

当您将JSONObject传递给@Body注解时,此JSONObject被序列化,因此HTTP请求正文包含:{“名称值对”:“实际JSON对象”}。

解决方案:

将实际的JAVA对象传递给@Body注解,而不是它对应的JSONObject。GSON将负责将它转换为JSON表示。
例如:

class HTTPRequestBody {
   String key1 = "value1";
   String key2 = "value2";
   ...
}

// GSON will serialize it as {"key1": "value1", "key2": "value2"}, 
// which will be become HTTP request body.

public interface MyService {
    @Headers({"Content-type: application/json",
              "Accept: */*"})
    @POST("/test")
    void postJson(@Body HTTPRequestBody body, Callback<Response> callback);
}

// Usage
MyService myService = restAdapter.create(MyService.class);
myService.postJson(new HTTPRequestBody(), callback);

替代解决方案:

如果您仍然希望将原始JSON作为HTTP请求主体发送,请遵循Retrofit作者here提到的解决方案。
建议的解决方案之一是使用TypedInput

public interface MyService {
  @POST("/test")
  void postRawJson(@Body TypedInput body, Callback<Response> callback);
}

String json = jsonRequest.toString();
TypedInput in = new TypedByteArray("application/json", json.getBytes("UTF-8"));
myService.postRawJson(in, callback);
dldeef67

dldeef672#

请使用com.google.gson.jsonObject,而不要使用org.json.jsonObject

JSONObject jsonRequest = new JSONObject();
jsonRequest.put("xxxx", "zzzzzzz");
jsonRequest.put("yyyy", "uuuuuuu");

更改为

JsonObject jsonRequest = new JsonObject();
jsonRequest.addProperty("xxxx", "zzzzzzz");
jsonRequest.addProperty("yyyy", "uuuuuuu");

然后在界面

public interface MyService {
    @Headers({"Content-type: application/json",
              "Accept: */*"})
    @POST("/test")
    void testFunction(@Body JsonObject jsonObject, Callback<Response> callback);
}

JSONObject类使用变量名nameValuePairs保存LinkedHashMap中的值,当Gson尝试将JSONObject的示例转换为JSON时,GSON保存了结构(其中包含变量nameValuePairs)。这导致了此问题。

daupos2t

daupos2t3#

必须将JSON对象转换为GSON的JSON对象
沿着这条路走

JsonParser jsonParser = new JsonParser();
  JsonObject jsonObject = (JsonObject)jsonParser.parse(actualjsonobject.toString());

然后传递到主体

HashMap<String,Object> body=new HashMap();

 body.put("content",jsonObject);
46scxncf

46scxncf4#

感谢13KZ,为我指明了正确的方向,在这里充实它就是我现在要解决的问题。
定义

private JsonObject gsonResultTwoWeek;
private JsonObject gsonResultDay;
private JsonObject gsonResult;

初始化

gsonResult = new JsonObject();
gsonResultDay = new JsonObject();
gsonResultTwoWeek = new JsonObject();

用途

gsonResultDay.addProperty(epoch, value);

其中data是一个字符串,value是一个int,在for循环中添加多个值
然后把它们组合在一起

gsonResult.addProperty("accounts", 2);
gsonResult.add("todaydata", gsonResultDay);
gsonResult.add("2weekdata", gsonResultTwoWeek);

最后我的接口

public interface ApiInterface {

    @POST("/groupdata")
    void postGroupData(@Body JsonObject body,Callback<StatusResponse> cb);

}

我的服务器上显示的是

{"accounts":2,"todaydata":{"1423814400":89,"1423816200":150,"1423818000":441},"2weekdata":{"1423699200":4869,"1423785600":1011}}
6rvt4ljy

6rvt4ljy5#

看起来您正在尝试传输实际的JSONObject,而不是对象的JSON文本字符串表示。查看JSONObject类的规范,您应该使用.toString()方法来获取由JSONObject保存的数据结构的JSON文本表示。因此,您应该能够更改:

public interface MyService {
    @Headers({"Content-type: application/json",
              "Accept: */*"})
    @POST("/test")
    void testFunction(@Body JSONObject jsonObject, Callback<Response> callback);
}

至:

public interface MyService {
    @Headers({"Content-type: application/json",
              "Accept: */*"})
    @POST("/test")
    void testFunction(@Body String jsonObject.toString(), Callback<Response> callback);
}

唯一的变更是JSONObject jsonObject变更为String jsonObject.toString()
或者,您也可以直接使用JSON中的字符串,将'"name_value_pairs": {'替换为'',将字符串中的最后一个'}'替换为'',这两个替换将生成一个有效的JSON文本对象,空格缩进对人来说看起来并不正确,但是解析JSON字符串的机器并不关心空格是否正确。

ztyzrc3y

ztyzrc3y6#

我的解决方案基于13KZ的

public class MyRequest {

  @SerializedName(Constants.ID)
  private String myID;
  @SerializedName(Constants.PARAM_ANSWERS)
  private JsonObject answers;

     public MyRequest(String id, Hasmap<String, String> answers) {
         this.myID = id;
         this.answers = new JsonObject();
         for (String s: answers.keySet()) {
             this.answers.addProperty(s, answers.get(s));
         }
     }
}
yuvru6vn

yuvru6vn7#

JSONObject jsonRequest = new JSONObject();
                    try {
                        jsonRequest.put("abc", "test");
                        jsonRequest.put("cba", "tye");
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                    Log.d("jsonobject", "onClick: "+jsonRequest);

    (result: {"abc":"test","cba":"tye"})

    JsonParser jsonParser = new JsonParser();
    JsonObject jsonObject = (JsonObject)jsonParser.parse(jsonRequest.toString());

                Log.d("jsonobjectparse", "onClick: "+jsonObject);

(result: {"abc":"test","cba":"tye"})

Once you are put the values into the jsonObject pass to the jsonParser it will solve the issue

thats all. enjoy your coding.
rur96b6h

rur96b6h8#

nameValuePairs in retfrofit error

get this type
{
  "nameValuePairs": {
    "email": "mailto:test1@gmail.com",
    "password": "12345678"
  }
}

need this type 
 {
    "email": "mailto:test1@gmail.com",
    "password": "12345678"
  }

    @POST("login")
    suspend fun getLogin(@Body jsonObject: RequestBody) : Response<LoginModel>
    
    
    
    In Repository Class
      Add this line for conver in json utf-8 fomat
      val body = jsonObject.toString().toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
    
    class LoginRepository constructor(private val  retrofitService: RetrofitService) {

    suspend fun getLogin(jsonObject: JSONObject): NetworkState<LoginModel> {
        val body = jsonObject.toString().toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())


        val response = retrofitService.getLogin(body)
        return if (response.isSuccessful) {
            val responseBody = response.body()
            if (responseBody != null) {
                NetworkState.Success(responseBody)
            } else {
                NetworkState.Error(response)
            }
        } else {
            NetworkState.Error(response)
        }
    }
}

相关问题