2014-09-24 9 views
14

Pracuję nad projektem Android, który potrzebuje JSONObject dla treści mojego żądania POST. Po oddaniu kluczy i wartości JSON mam następujący wiersz:Jak mogę usunąć klucz nameValuePairs z JSONObject?

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

ale serwer dostał następujące:

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

Już spróbował JSONStringer ale to nie było naprawdę pomocne, ponieważ Content-Type żądania to application/json.

UPDATE

Nie próbuję skonstruować JSONObject bo to już zrobione za pomocą poniższego wiersza kodu (tak samo podane przez @osayilgan):

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

Tu nie ma problem. Opisany poniżej interfejs służy do komunikacji z serwerem.

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

Serwer otrzymał żądanie z drugim JSON-em jako treścią, co jest niezadowalające. Zauważam, że klucz name_value_pairs jest automatycznie dodawany do obiektu.

Czy ktoś wie, jak mogę to naprawić?

+0

Czy możesz opublikować kod, którego używasz, aby uzyskać t on dwa bloki JSON? Domyślam się, że otrzymujesz zawartość 'name_value_pairs', a nie zawartość obiektu, który zawiera. – emerssso

+0

Uaktualniam pytanie. Skonstruowałem pierwszy, ale klucz name_value_pairs jest automatycznie dodawany, gdy przekazałem JSONObject jako treść mojego żądania. – 13KZ

+0

Nie chcę, aby klucz "nazwa wartości par" został dodany do mojego obiektu json. Masz pomysł, jak temu zapobiec? – Nil

Odpowiedz

16

Issue:

Modernizacja domyślnie używa GSON przekonwertować ciał HTTP do iz JSON. Obiekt określony za pomocą adnotacji @Body zostanie przekazany do GSON w celu serializacji, która zasadniczo konwertuje obiekt JAVA na reprezentację JSON. Ta reprezentacja JSON będzie treścią żądania HTTP.

JSONObject przechowuje wszystkie odwzorowania klucz-wartość w zmiennej członkowskiej o nazwie nameValuePairs. Oto fragment realizacji JSONObject:

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

Po przejechaniu JSONObject do @Body adnotacji, to JSONObject jest seraliazed, stąd ciało żądania HTTP zawiera: { "nameValuePairs": "rzeczywisty obiekt JSON"}.

Rozwiązanie:

zdać rzeczywisty obiekt Java @Body adnotacji, to nie odpowiada JSONObject. GSON zajmie się przekształceniem go w reprezentację JSON.

Dla np.

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); 

Alternatywne rozwiązanie:

Jeśli nadal chcesz wysłać surowego JSON jako żądania HTTP ciała, a następnie rozwiązanie wspomniane przez autora here modernizowanych.

Jednym z proponowanych rozwiązań jest użycie 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); 
+6

Dzięki za odpowiedź. To naprawdę pomocne. Znalazłem inny sposób na uniknięcie kluczowej nazwy ValuePairs.Zamiast używać JSONObject z Androidem, pracuję z JsonObject z GSON i konstruuję obiekt za pomocą metody addProperty (właściwość String, _THEVALUE_). – 13KZ

0

Wydaje się, że próbujesz przekazać faktyczną JSONObject raczej JSON reprezentacji tekst string obiektu. Spojrzenie na specyfikację klasy JSONObject pokazuje, że powinieneś używać metody .toString(), aby uzyskać tekstową reprezentację JSON struktury danych przechowywanej przez JSONObject. Zatem powinieneś być w stanie zmienić:

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

do:

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

Jedyną zmianą jest JSONObject jsonObject do String jsonObject.toString().

Alternatywnie, można brute force go po prostu biorąc ciąg znaków, który trzeba mieć na JSON i zastąpienie '"name_value_pairs": {' z '' a ostatnim '}' w ciągu z ''. JSON to tylko ciąg tekstu. Poza tym, że jest nieelegancki, nie ma powodu, aby nie móc manipulować tekstem. Te dwa zamienniki będą skutkować prawidłowym obiektem tekstowym JSON. Wcięcie spacji nie będzie wyglądało poprawnie dla człowieka, ale maszyna analizująca łańcuch JSON nie dba o to, czy białe spacje są poprawne.

+0

moja maszyna dba. – CQM

1

Dzięki 13KZ skierował mnie we właściwym kierunku, a do tego, co jest teraz, muszę rozwiązać ten problem.

Definicje

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

Uruchomienie

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

Zastosowanie

gsonResultDay.addProperty(epoch, value); 

gdzie dane jest ciągiem i wartość jest int w moim przypadku i jest w pętli for, aby dodać wielokrotność wartości

A potem ciągnąć to wszystko razem

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

Wreszcie mój interfejs

public interface ApiInterface { 

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

} 

Co uderza mój serwer jest to

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

Moje rozwiązanie opiera się na 13KZ na

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)); 
     } 
    } 
} 
Powiązane problemy