I'm having a bit of trouble with GSON reading my API response JSON.
My API data returns an object with a status code, message and a data object.
The problem that I have with GSON, is that I can't figure out how to work with it properly.
For example, my API response can look like this.
{
"code": 200,
"message": "",
"data": {
"auth_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"points": 42850
}
}
OR
{
"code": 200,
"message": "",
"data": {
"items": [
{
"title" : "value"
},
{
"title" : "value"
}
]
}
}
OR others
The first response, which is a login response would be a class LoginResponse.class
public class LoginResponse {
private String auth_token;
private int points;
public String getAuthToken(){
return auth_token;
}
public int getPoints(){
return points;
}
}
and I'd use
LoginResponse response = gson.fromJson(json, LoginResponse.class);
But, how can I create a class so I can access the status code, message and the data? (which could be any of the response classes that I have)
I've looked at TypeAdapterFactory and JsonDeserializer, but couldn't get my head around it.
So, if anyone can find a SO answer that answers this question, that'd be great because I couldn't find one, or if you know how to do just this.
You could have code and message as normal, and then data could be a Map<String, Object> that you would have to interpret at runtime depending on the code or whatever you use to differentiate how the response should look.
You can solve it by doing this:
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
JsonParser parser = new JsonParser();
JsonObject rootObejct = parser.parse(json).getAsJsonObject();
JsonElement dataElement = rootObejct.get("data");
LoginResponse response = gson.fromJson(dataElement, LoginResponse.class);
Related
I am getting below response when I am calling an API.
Response postRequestResponse = ConnectionUtil.getwebTarget()
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true)
.path("bots")
.path(ReadSkillID.readSkillId())
.path("dynamicEntities").path(dynamicEntityID)
.path("pushRequests").path(pushRequestID).path(operation)
.request()
.header("Authorization", "Bearer " + ConnectionUtil.getToken())
.get();
Below output I am getting.
{
"createdOn": "2020-08-17T12:19:13.541Z",
"updatedOn": "2020-08-17T12:19:23.421Z",
"id": "C84B058A-C8F9-41F5-A353-EC2CFE7A1BD9",
"status": "TRAINING",
"statusMessage": "Request Pushed into training, on user request"
}
I have to return this output to client with an additional field in the response. How can modify the above response and make it
{
"EntityName": "NewEntity", //New field
"createdOn": "2020-08-17T12:19:13.541Z",
"updatedOn": "2020-08-17T12:19:23.421Z",
"id": "C84B058A-C8F9-41F5-A353-EC2CFE7A1BD9",
"status": "TRAINING",
"statusMessage": "Request Pushed into training, on user request"
}
I am adding this additional field here
"EntityName": "NewEntity"
How can I do that. many things I tried but got exception.
get JSON from postRequestResponse (i have no idea what framework you are using, so you have to figer it out on your own, but the Response datatype will probably have a getResponseBody or similar method returing the JSON)
add EntityName
serialize it again to json.
class YourBean {
#Autowired
private ObjectMapper objectMapper;
public void yourMethod() {
// 1
final InputStream jsonFromResponse = ...
// 2
Map dataFromResponse = objectMapper.readValue(jsonFromResponse, Map.class);
dataFromResponse.put("EntityName", "NewEntity");
// 3
final String enrichedJson = objectMapper.writeValueAsString(dataFromResponse);
}
}
enrichedJson contains EntityName and whatever comes from the API.
I am working on a jersey - java project where I have to get the json data in string format and parse each data separately. I am able to get the response in string using post method. When I try to use JSON lib to parse the string data class not found exception is produced. I want the returned string to be split up. Below is my json.
{
"startdate": "11/11/11",
"enddate": "12/12/12",
"operation_name": "task1",
"user_id": "user1",
"operation_key": ["KKMM-025", "SFF-025", "TTR-022"]
}
Resource method
#POST
#Path("OpertaionDetails")
#Consumes({MediaType.APPLICATION_JSON , MediaType.APPLICATION_XML})
public Response CreateOperations(String incoming_data) throws Exception
{
try
{
JSONParser parse = new JSONParser(); // class not found exceptin i have added the lib properly its working fine when it is used in main method of java.
JSONObject jobj = (JSONObject)parse.parse(incoming_data);
JSONObject Jstart_date = (JSONObject) jobj.get("startdate");
// this data to be paresed
System.out.print("incomingData"+incoming_data);
}
catch(Exception e)
{
e.printStackTrace();
}
return Response.ok(incoming_data).build();
}
I am currently working on a project where i need to make a rest call to an external API and parse the JSON response to a POJO and return back the POJO as JSON for another rest request. I am able to parse the JSON response, but my requirement is to parse only one particular node from it. How can i achieve this? I am using Spring Boot and Spring Rest Template to make the external rest call. Please help!!!
#RestController
public class ProductsController {
private static final Logger LOGGER = LoggerFactory.getLogger(ProductsController.class);
#RequestMapping(value = "/myRetail/product/{id}", method = RequestMethod.GET, produces = {
MediaType.APPLICATION_JSON_UTF8_VALUE, MediaType.APPLICATION_XML_VALUE })
#ResponseBody
public Item getSchedule(#Valid Payload payload) {
String URL = "<External API>";
LOGGER.info("payload:{}", payload);
Item response = new Item();
RestTemplate restTemplate = new RestTemplate();
Item item = restTemplate.getForObject(URL, Item.class);
LOGGER.info("Response:{}", item.toString());
return response;
}
}
JSONResponse (This is a part of whole i receive)
{
"ParentNode": {
"childNode": {
"att": "13860428",
"subchildNode 1": {
"att1": false,
"att2": false,
"att3": true,
"att4": false
},
"att4": "058-34-0436",
"att5": "025192110306",
"subchildenode2": {
"att6": "hello",
"att7": ["how are you", "fine", "notbad"],
"is_required": "yes"
},
............
}
Required JSONpart from the above whole response:
"subchildenode2": {
"att6": "hello",
"att7": ["how are you", "fine", "notbad"],
"is_required": "yes"
}
Use the org.json library. With this library you can parse the payload to a JSONObject and navigate to your required subpart of the document.
So you have to get the payload as a JSON-String and parse it to the JSONObject from the library. After that you can navigate to your required subpart of the document and extract the value and then parse it to your required Java POJO.
Have look at: How to parse JSON
Just map the path to the needed object:
{
"ParentNode": {
"childNode": {
"subchildenode2": {
"att6": "hello",
"att7": ["how are you", "fine", "notbad"],
"is_required": "yes"
}
}
}
And then simply:
Response responseObject= new Gson().fromJson(json, Response.class);
SubChildNode2 att6 = responseObject.getParentNode().getChildNode().getSubChildNode2();
let's say I've got a REST API which I could get list of books by invoking following retrofit 2 request.
public interface AllRecordsFromRequestInterface {
#GET("books/all")
Call<List<TrackInfo>> operation(#Header("Authorization") String authentication_token);
}
and API response:
[
{
"id": "1",
"title": "The Catcher in the Rye",
"author":"J. D. Salinger"
},
{
"id": "2",
"title": "The Great Gatsby",
"author":"F. Scott Fitzgerald"
}
]
I use GsonConverterFactory to convert json to a Model. here is my model class
public class Book{
private int id;
private String title;
private String author;
}
I'm using a authentication token to authorize myself to API as it can be seen in my request. some times other response are received rather than above response because of token expiration or something else. for example:
{
"status": "error",
"message": "Expired token"
}
what is the proper way to handle dynamic responses (with known structure) in retrofit 2?
you have multiple choices:
1-change your API:(this one is standard)
change it like this for every response and if the user failed with authentication leave the result null or if authentication was successful put the list in the result.
{
"status" : "error/success"
"message" : ...
"result" : ....
}
2- you can give Object type to retrofit and after the response was successful you can cast it to one of your models, using "instance of" syntax.
public interface AllRecordsFromRequestInterface {
#GET("books/all")
Call<Object> operation(#Header("Authorization") String authentication_token);
}
I am using Drupal Services along with the JSON Services module as a data source.
I am using the DrupalCloud library, https://github.com/skyred/DrupalCloud/wiki, and am wondering how to best process the results that I receive from a userLogin() call.
If the call itself fails we get:
{
"#error": true,
"#message": "Some message"
}
If the call succeeds but the login credentials are wrong:
{
"#error": false,
"#data": {
"#error": true,
"#message": "Some message"
}
}
If the call success and the login credentials are correct, it returns:
{
"#error": false,
"#data": {
"sessid": "foo",
"user": {
"uid": "69",
"name": "Russell Jones",
"pass": "bar",
"mail": "russell#test.net",
"roles": {
"2": "authenticated user",
"5": "Student"
},
}
}
}
How do I go about using this data meaningfully? Or rather, how do I test to see if the call worked, and if the login was successful or not.
Have you searched older posts? Like this post, from 2 hours ago:
how to convert json object into class object
or: JSON Parsing in Android
Or just search for yourself: Search: Android+Json
Should give you a good idea..
This is one way to parse the last JSON message in your question:
public void readJsonString(String jsonString) throws JSONException
{
JSONObject jsonObject = new JSONObject(jsonString);
boolean error = jsonObject.getBoolean("#error");
if (!error)
{
JSONObject data = jsonObject.getJSONObject("#data");
String sessionId = data.getString("sessid");
JSONObject user = data.getJSONObject("user");
int uid = user.getInt("uid");
String name = user.getString("name");
// you get the pattern, same way with the other fields...
}
}