Как удалить ключ nameValuePairs из JSONObject?
Я работаю над проектом Android, которому нужен JSONObject для моего запроса POST.
После ввода ключей и значений JSON я получил следующую строку:
{
"xxxx":"zzzzzzz",
"yyyy":"uuuuuuu"
}
Но сервер получил следующее:
{
"name_value_pairs": {
"xxxx":"zzzzzzz",
"yyyy":"uuuuuuu"
}
}
Я уже пробовал JSONStringer, но это было не очень полезно, потому что Content-Type
запроса application/json
.
UPDATE
Я не пытаюсь создать 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
автоматически добавляется к объекту.
Кто-нибудь знает, как я могу это исправить?
Ответы
Ответ 1
Проблема:
Дооснащение по умолчанию использует GSON для преобразования тел HTTP в JSON и обратно. Объект, указанный с аннотацией @Body, будет передан GSON для сериализации, который в основном преобразует объект JAVA в представление JSON. Это JSON-представление будет телом HTTP-запроса.
JSONObject сохраняет все сопоставление значений ключей в переменной-члене по имени nameValuePairs
.
Вот выдержка из реализации JSONObject:
public class JSONObject {
...
private final Map<String, Object> nameValuePairs;
...
}
Когда вы передаете JSONObject в аннотацию @Body, этот JSONObject является seraliazed, поэтому тело запроса HTTP содержит: { "nameValuePairs": "фактический объект 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 здесь.
Одним из предлагаемых решений является использование 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);
Ответ 2
Благодаря 13KZ, указал мне в правильном направлении, и для того, чтобы отразить это, я сейчас должен решить эту проблему.
Определения
private JsonObject gsonResultTwoWeek;
private JsonObject gsonResultDay;
private JsonObject gsonResult;
Инициализация
gsonResult = new JsonObject();
gsonResultDay = new JsonObject();
gsonResultTwoWeek = new JsonObject();
Использование
gsonResultDay.addProperty(epoch, 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}}
Ответ 3
Похоже, вы пытаетесь передать фактическое JSONObject
скорее текстовое представление JSON объекта. Взгляд на спецификацию класса 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 - это всего лишь строка текста. Кроме того, что это неэлегантно, нет причин, по которым вы не можете манипулировать текстом. Эти две замены приведут к действительному текстовому объекту JSON. Отступ пробелов не будет выглядеть правильно для человека, но машина, анализирующая строку JSON, не заботится о правильности пробелов.
Ответ 4
Мое решение основано на
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));
}
}
}
Ответ 5
Вы должны преобразовать JSONObject в JsonObject
следовать по этому пути
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = (JsonObject)jsonParser.parse(actualjsonobject.toString());
затем пройти в теле
HashMap<String,Object> body=new HashMap();
body.put("content",jsonObject);
Ответ 6
Используйте 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, хранящий значения в LinkedHashMap
с именем переменной nameValuePairs
Когда Gson пытается преобразовать экземпляр JSONObject в JSON, GSON сохраняет структуру (которая имеет переменную nameValuePairs
). Это вызывает эту проблему.