I'm following this guide - https://github.com/excilys/androidannotations/wiki/Rest%20API and I am trying skip JSON<->POJO conversion and work on pure JSONObject (or gson's JsonObject). What should I write as an server's answer?
#Rest("url")
public interface JsonRest
{
#Get("/getjson")
JSONObject getTime();
// or... ?
#Get("/getjson")
ResponseEntity<JSONObject> getTime();
// or... ?
#Get("/getjson")
JsonObject getTime();
}
In all cases I am getting "{}" as a response, but it's contains correct data after POJO conversion. Which HTTPMessageConverter should I provide? Thanks for any help.
Simply add GsonHttpMessageConverter to RestTemplate and try this:
#Get("/getjson")
JsonElement getSomething();
I don't think this is supported by Spring Android RestTemplate by default. You should probably provide your own provider.
You could look at how GsonHttpMessageConverter is implemented here and then implement your own solution based on that.
Related
The problem is next.
In response I have JSON like
{
object: {
// a lot of different fields
}
}
I use Retrofit with gson parser. What I really need is just this object. I don't want to create class for response with the only one field. All responses server send in a such manner. As far I understand somewhere I need place simple code for fetching that one object and then use default parser for it.
Probably sorry for stupid question. I used Volley and there was quite a different approach.
Instead of creating a special class to handle this (and another special class for every other server response), just use Map<String, YourRealObjectType>. Then use this method to extract the YourRealObjectType instance for each response:
public static <T> T getFirstValue(Map<String, T> map) {
return map.values().iterator().next();
}
you can convert class into JsonObject class. then cal iterate all the elements in it one by one
#Get
ObservablegetData();
Note : use JsonObject not JSONObject
I was wondering if somewhere out there exists a java library able to query a JSONObject. In more depth I'm looking for something like:
String json = "{ data: { data2 : { value : 'hello'}}}";
...
// Somehow we managed to convert json to jsonObject
...
String result = jsonObject.getAsString("data.data2.value");
System.out.println(result);
I expect to get "hello" as output.
So far, the fastest way I have found is using Gson:
jsonObject.getAsJsonObject("data").getAsJsonObject().get("data2").getAsJsonObject("value").getAsString();
It's not actually easy to write and read. Is there something faster?
I've just unexpectedly found very interesting project: JSON Path
JsonPath is to JSON what XPATH is to XML, a simple way to extract parts of a given document.
With this library you can do what you are requesting even easier, then my previous suggestion:
String hello = JsonPath.read(json, "$.data.data2.value");
System.out.println(hello); //prints hello
Hope this might be helpful either.
While not exactly the same, Jackson has Tree Model representation similar to Gson:
JsonNode root = objectMapper.readTree(jsonInput);
return root.get("data").get("data2").get("value").asText();
so you need to traverse it step by step.
EDIT (August 2015)
There actually is now (since Jackson 2.3) support for JSON Pointer expressions with Jackson. So you could alternatively use:
return root.at("/data/data2/value").asText();
First of all, I would recommend consider JSON object binding.
But in case if you get arbitrary JSON objects and you would like process them in the way you described, I would suggest combine Jackson JSON processor along with Apache's Commons Beanutils.
The idea is the following: Jackson by default process all JSON's as java.util.Map instances, meanwhile Commons Beanutils simplifies property access for objects, including arrays and Map supports.
So you may use it something like this:
//actually it is a Map instance with maps-fields within
Object jsonObj = objectMapper.readValue(json, Object.class);
Object hello = PropertyUtils.getProperty(jsonObj, "data.data2.value")
System.out.println(hello); //prints hello
You can use org.json
String json = "{ data: { data2 : { value : 'hello'}}}";
org.json.JSONObject obj = new org.json.JSONObject(json);
System.out.println(obj.query("/data/data2/value"));
I think no way.
Consider a java class
class Student {
Subject subject = new Subject();
}
class Subject {
String name;
}
Here if we want to access subject name then
Student stud = new Student();
stud.subject.name;
We cant access name directly, if so then we will not get correct subject name. Like here:
jsonObject.getAsJsonObject("data")
.getAsJsonObject()
.get("data2")
.getAsJsonObject("value")
.getAsString();
If you want to use same like java object then use
ClassName classObject = new Gson().fromJson(JsonString, ClassName.class);
ClassName must have all fields to match jsonstring. If you have a jsonobject inside a jsonobject then you have to create separate class like I'm doing in Student and Subject class.
Using Java JSON API 1.1.x (javax.json) one can make use of new JavaPointer interface. Instance implementing this interface can be considered to some extend as kind of XPath expression analog (see RFC-6901 for details). So in your case you could write this:
import javax.json.*;
//...
var jp = Json.createPointer("/data/data2/value");
System.out.println(jp.getValue(jsonObject));
In 1.1.4 version of JSON there's also nice addition to JsonStructure interface (which is implemented by JsonObject and JsonArray), namely getValue(String jsonPointer). So it all comes down to this simple one-liner:
System.out.println(jsonObject.getValue("/data/data2/value"));
I have a Json of this type :
{
"4f958ef28ecd651095af6ab6": {
enormous JsonObject
}
}
the "4f958ef28ecd651095af6ab6" is different each time (but I know what it will be as it is a parameter of my api call), it corresponds to the id of the following object. I have a Gson-configured model to parse the enormous JsonObject.
My question is : is it performant to use simply
new JSONObject(jsonresponse).getJSONObject("4f958ef28ecd651095af6ab6")
and parse with Gson from there ?
Is there a better way to do so ?
I guess the real question would be, what does "new JSONObject(String)" realy do ?
Thanks
What you are doing is:
You load all the Json string into the phone memory (memory issue + long time to load entirely)
You create a big JSONObject (same issues) in order to have access to each key.
You write few code but this is not the most performant solution.
To minimized the memory impact and accelerate the operation of objects' creation, you can use Gson in stream mode.
By directly read the input stream, you avoid to load too much data and you can directly start to populate your object piece by piece.
And about the JSONObject, it will mostly check if your json string is correct (or it will throw a JsonException) and it will let you look into the object when you search for a key and its value.
I would recommend use hybrid (native and gson) since i am not sure how to get unknown jsonobject with GSON.
You need to get your response as a JSONArray, then itarete for each JSONObject. You can experiment parsing code as trying. Please check JSONArray.getJSONObject(int index) method. Then we can use GSON to get our data model to get known attributes.
If you can post complete json data, we can give it chance to parse together.
I am using Retrofit for server calls. I need to send a JSONArray to the server. My JSONArray looks like -
[{"callName”:”xxx”},{“inputData":{"deviceImei”:”xxxx”,”appVersionUser”:”x”,”osVersion”:”x”,”osType”:”x”,”deviceToken”:”xxxx”}}]
I am using RetroFit version 1.9.0 . I tried to use #BODY. But I am getting this error -
retrofit.RetrofitError: APIClass.GetClientAuthentication: #Body parameters cannot be used with form or multi-part encoding"
My Api function declaration is,
#FormUrlEncoded
#POST("/XYZ")
void GetClientAuthentication(#Body JSONArray jArray,
Callback<AuthenticationCallBack> aPOJOCallback);
Can anybody help?
Thanks in advance.
Hey i solved it finally
At the receiving part i took response in JSONElement and converted it to POJO class like below. AuthenticationErrorJsonResponse.java is my POJO class.
ArrayList<AuthenticationErrorJsonResponse> yourArray = new Gson().fromJson(authenticationJsonResponse.toString(),
new TypeToken<List<AuthenticationErrorJsonResponse>>(){}.getType());
I want to send POST request to server. I have to pass JSON object as a parameter, and get JSON as a response, but I am getting this error:
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [com.package.Response] and content type [application/octet-stream]
Code
Sending request:
#RestService
RestClient restClient;
...
String json = "{\"param\":3}";
restClient.getRestTemplate().getMessageConverters().add(new GsonHttpMessageConverter());
Response res = restClient.send(json);
RestClient
#Rest("http://my-url.com")
public interface RestClient
{
#Post("/something/")
Response send(String json);
RestTemplate getRestTemplate();
void setRestTemplate(RestTemplate restTemplate);
}
I'm using these JAR files:
spring-android-rest-template-1.0.0.RC1
spring-android-core-1.0.0.RC1
spring-android-auth-1.0.0.RC1
gson-2.2.2
What I'm doing wrong? When I change send parameter to JSONObject I am getting the same error.
Btw. AA docs are really enigmatic - can I use Gson anyway? Or should I use Jackson? Which file do I need to include then?
Thanks for any help!
You can use RestTemplate with either Gson or Jackson.
Gson is fine and easier to use of you have small json data set. Jackson is more suitable if you have a complex / deep json tree, because Gson creates a lot of temporary objects which leads to stop the world GCs.
The error here says that it cannot find a HttpMessageConverter able to parse application/octet-stream.
If you look at the sources for GsonHttpMessageConverter, you'll notice that it only supports the mimetype application/json.
This means you have two options :
Either return the application/json mimetype from your content, which would seam quite appropriate
Or just change the supported media types on GsonHttpMessageConverter :
String json = "{\"param\":3}";
GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
converter.setSupportedMediaTypes(new MediaType("application", "octet-stream", Charset.forName("UTF-8")));
restClient.getRestTemplate().getMessageConverters().add(converter);
Response res = restClient.send(json);
I just had this problem. After several hours I realised that the class I was passing in to the RestTemplate.postForObject call had Date variables. You need to make sure it only contains simple data types. Hope this helps someone else!
I have to modify it little to work:
final List<MediaType> list = new ArrayList<>();
list.addAll(converter.getSupportedMediaTypes());
list.add(MediaType.APPLICATION_OCTET_STREAM);
converter.setSupportedMediaTypes(list);