Reputation: 270
I'm using java GAE server. I store List on my entity (as strings are very limited in length in GAE). I send Map to the client through the Endpoint, and I put this list under some key. Then I retrieve this list on Android client - and I get classcast exception. It appears that HashMap< String, Object > sent from GAE server is seen as JsonMap on Client. Whatever. I proceed, I retrieve my List... and how surprised I was to find out that on the client I got List< ArrayMap >, and on this ArrayMap, my Text is under the key named "value".
There is even more. Under one of the keys in the JsonMap, I had a null value. I retrieve it... and it appears as Object (which is not null). Calling toString on this object gives me some crappy string...
Could anyone tell me why these things are happening? Sure, I can just accept how it, but its strange and not logical, and undocumented... Why my List< Text > magically converts into List< ArrayMap >? How likely is that it varies with, lets say, Android version, or, I don't know, with weather outdoor?... Anyone could help me understand these situations? Or point me some relevant documentation / articles?
Example server-side:
@ApiMethod(name = "retrievePlayer")
public Map<String, Object> retrievePlayer(Map<String, Object> data, User user) throws Exception, OAuthRequestException, IOException {
Map<String, Object> result = new HashMap<String, Object>();
List<Text> list = new ArrayList<Text>();
list.add(new Text("something"));
result.put("myList", list);
result.put("myNull", null);
return result;
}
On the client side, the "result" is of type JsonMap. The "myList" is of type ArrayList (ok). myList.get(0) is of type ArrayMap, and its one-element ArrayMap - the element inside this map has key named "value", and a value of "something". The "myNull" is of type Object and is not null, its toString() method shows something like [Ljava.lang.Object;@1db9742.
I resolved the issues by returning empty string instead of null. For the List< Text >, I iterate through it on and add all the Texts as Strings to new List< String >, and then return this new list (but it costs cpu usage on the server)... I thought it will work more predictably and out-of-the-box.
Upvotes: 3
Views: 135
Reputation: 29
In this particular example, the method will return an instance of Map<< String, Object>>. If you try to call this endpoint using https://your_app_id.appspot.com/_ah/api/explorer, the json return will be { "myList" : { { "value": "something"} }, "myNull" : null }.
The returned json seems to be correct and a null is returned for "myNull". The reason you are getting an instance of Object and not null is because of the handling of JSON null by the JSON library. Please check this link for more explanation (JSON null section).
As for why the List<< Text>> magically converts into List<< ArrayMap>>, this is because you define the return as an instance of Map<< String, Object>> and the returned json does not contain any type information. I think when converting to client objects the type information is obtained from the generated client code which is based on the signature of the ApiMethod.
Upvotes: 1