Comment puis-je supprimer la clé nameValuePairs du JSONObject?
je travaille sur un projet Android qui a besoin d'un JSONObject pour le corps de ma requête. Après avoir mis les clés et les valeurs du JSON, j'ai obtenu la ligne suivante:
{
"xxxx":"zzzzzzz",
"yyyy":"uuuuuuu"
}
Mais le serveur le suivant:
{
"name_value_pairs": {
"xxxx":"zzzzzzz",
"yyyy":"uuuuuuu"
}
}
j'ai déjà essayé un JSONStringer mais il n'était pas vraiment utile parce que le Content-Type
de la demande est application/json
.
UPDATE
Je n'essaie pas de construire un JSONObject parce que c'est déjà fait en utilisant la ligne de code suivante (la même donnée par @osayilgan):
JSONObject jsonRequest = new JSONObject();
jsonRequest.put("xxxx", "zzzzzzz");
jsonRequest.put("yyyy", "uuuuuuu");
Voici pas le problème. L'interface décrite ci-dessous est utilisé pour communiquer avec le serveur.
public interface MyService {
@Headers({"Content-type: application/json",
"Accept: */*"})
@POST("/test")
void testFunction(@Body JSONObject jsonObject, Callback<Response> callback);
}
le serveur a reçu la requête avec le second JSON comme corps ce qui est décevant. Je remarque que la touche name_value_pairs
est automatiquement ajoutée à l'objet.
quelqu'un sait comment je peux résoudre ce problème?
4 réponses
Problème:
Retrofit par défaut utilise GSON pour convertir les corps HTTP en et à partir de JSON. L'objet spécifié avec l'annotation @Body sera passé à GSON pour la sérialisation, qui convertit essentiellement L'objet JAVA en représentation JSON. Cette représentation JSON sera le corps de requête HTTP.
JSONObject stocke tout le mappage des valeurs clés dans une variable membre par nom nameValuePairs
.
Voici un extrait de JSONObject application:
public class JSONObject {
...
private final Map<String, Object> nameValuePairs;
...
}
lorsque vous passez JSONObject à l'annotation @Body, ce JSONObject est seraliazed, donc le corps de requête HTTP contient: {"nameValuePairs": "actual JSON Object"}.
Solution:
passer L'objet JAVA réel à l'annotation @Body, pas JSONObject correspondant. GSON s'occupera de la convertir en représentation JSON.
Par exemple
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);
Alternative solution:
si vous souhaitez toujours envoyer raw JSON comme corps de requête HTTP, alors suivez la solution mentionnée par Retrofit author ici.
une des solutions suggérées est d'utiliser 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);
merci à 13KZ, m'a pointé dans la bonne direction, et pour l'étoffer ici est ce que je dois maintenant résoudre ce problème.
Définitions
private JsonObject gsonResultTwoWeek;
private JsonObject gsonResultDay;
private JsonObject gsonResult;
Initialisation
gsonResult = new JsonObject();
gsonResultDay = new JsonObject();
gsonResultTwoWeek = new JsonObject();
Utiliser
gsonResultDay.addProperty(epoch, value);
où les données sont une chaîne de la valeur et l'int dans mon cas, et est dans une boucle for pour ajouter plusieurs valeurs
Et puis pour tirer tous ensemble
gsonResult.addProperty("accounts", 2);
gsonResult.add("todaydata", gsonResultDay);
gsonResult.add("2weekdata", gsonResultTwoWeek);
enfin mon interface
public interface ApiInterface {
@POST("/groupdata")
void postGroupData(@Body JsonObject body,Callback<StatusResponse> cb);
}
ce qui touche mon serveur ce
{"accounts":2,"todaydata":{"1423814400":89,"1423816200":150,"1423818000":441},"2weekdata":{"1423699200":4869,"1423785600":1011}}
il semble que vous tentez de transmettre le JSONObject
plutôt la représentation de la chaîne de texte JSON de l'objet. Un coup d'oeil à la spécification de l' JSONObject
la classe montre que vous devez utiliser le .toString()
méthode pour obtenir la représentation texte JSON de la structure de données conservée par le JSONObject
. Ainsi, vous devriez être en mesure de modifier:
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);
}
Le seul changement JSONObject jsonObject
pour String jsonObject.toString()
.
alternativement, vous pouvez la forcer en prenant simplement la corde que vous avez du JSON et remplacer '"name_value_pairs": {'
''
et le dernier '}'
dans la chaîne de caractères ''
. JSON est juste une chaîne de texte. D'autres que d'être inélégant, il n'y a aucune raison que vous ne pouvez pas manipuler le texte. Ces deux remplacements donneront un objet texte JSON valide. L'indentation de l'espace blanc ne semblera pas correcte pour un humain, mais une machine qui analyse la chaîne JSON ne pas de soins si l'espace est correct.
ma solution est basée sur 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));
}
}
}