私はAndroidプロジェクトに取り組んでいます。このプロジェクトには、POSTリクエストの本文にJSONObjectが必要です。JSONのキーと値を入力した後、次の行:
{
"xxxx":"zzzzzzz",
"yyyy":"uuuuuuu"
}
しかし、サーバーは以下を取得しました:
{
"name_value_pairs": {
"xxxx":"zzzzzzz",
"yyyy":"uuuuuuu"
}
}
私はすでにJSONStringerを試しましたが、Content-Type
のリクエストはapplication/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);
}
サーバーは、2番目のJSONを本文として含むリクエストを受け取りましたが、これは残念です。キーname_value_pairs
が自動的にオブジェクトに追加されます。
誰かがこれを修正する方法を知っていますか?
問題:
後付けでは、デフォルトでGSONを使用して、HTTPボディとJSONの間の変換を行います。 @Bodyアノテーションで指定されたオブジェクトは、シリアル化のためにGSONに渡され、基本的にJavaオブジェクトをJSON表現に変換します。このJSON表現はHTTPリクエストボディになります。
JSONObjectは、すべてのキーと値のマッピングをnameValuePairs
という名前でメンバー変数に格納します。 JSONObject実装の抜粋を次に示します。
public class JSONObject {
...
private final Map<String, Object> nameValuePairs;
...
}
JSONObjectを@Bodyアノテーションに渡すと、このJSONObjectはシリアライズされるため、HTTPリクエストの本文には{"nameValuePairs": "actual JSON Object"}が含まれます。
ソリューション:
実際のJavaオブジェクトを対応するJSONObjectではなく@Bodyアノテーションに渡します。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);
代替ソリューション:
それでもHTTPリクエストボディとして未加工のJSONを送信する場合は、Retrofitの作成者が述べた解決策 here に従ってください。
提案された解決策の1つは 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);
jSONObjectをGSONのJsonObjectに変換する必要があります
この方法に従ってください
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = (JsonObject)jsonParser.parse(actualjsonobject.toString());
その後、体を渡します
HashMap<String,Object> body=new HashMap();
body.put("content",jsonObject);
org.json.JSONObjectの代わりにcom.google.gson.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);
}
LinkedHashMap
の値をnameValuePairs
の変数名で保持するJSONObjectクラス。GsonがJSONObjectのインスタンスをJSONに変換しようとすると、GSONは構造体(変数nameValuePairs
)。これがこの問題の原因です。
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}}
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.
私のソリューションは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));
}
}
}
オブジェクトのJSONテキスト文字列表現ではなく、実際のJSONObject
を送信しようとしているようです。 JSONObject
クラスの仕様を見ると、 .toString()
メソッドを使用して、JSONテキスト表現を取得する必要があることがわかります。 JSONObject
が保持するデータ構造。したがって、以下を変更できるはずです。
_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は単なるテキストのストリングです。それが上品である以外に、あなたがテキストを操作できない理由はありません。これら2つの置換により、有効なJSONテキストオブジェクトが生成されます。空白のインデントは人間には正しく見えませんが、JSON文字列を解析するマシンは、空白が正しいかどうかを気にしません。