how to get the value from json in android - json

Hi am getting the following json pentaho server,How i need to get date from this json
"queryInfo":{
"totalRows":"1"
},
"resultset":[
[
"09-09-2014"
]
],
"metadata":[
{
"colIndex":0,
"colType":"String",
"colName":"dt"
}
]
}

The best way is to use gson to deserilize the string:
Create a Class in a separate file.
import java.util.List;
import com.google.gson.annotations.SerializedName;
public class pentaho {
public QueryInfo queryInfo;
public static class QueryInfo {
public List<Result> metadata;
public static class Result {
#SerializedName("colIndex")
public String colIndexStr;
#SerializedName("colType")
public String colTypeStr;
#SerializedName("colName")
public String colNameStr;
}
}
}
In your Activity
public pentaho pentahoResult;
In your functions.
private void getJson(String jsonStr){
Gson gson = new Gson();
pentahoResult = gson.fromJson(jsonStr, pentaho.class);
Now you can go through each result if there is more than one by replacing the 0 with a loop variable like int i.
String MycolIndex = pentahoResult.d.results.get(0).colIndexStr;
String MycolType = pentahoResult.d.results.get(0).colTypeStr;
String MycolName = pentahoResult.d.results.get(0).colNameStr;
Have fun.

Related

Spring Boot adding attribute to XML element but NOT in JSON response

I am working on an API that produces both XML and JSON responses. I have one element in the response which requires an attribute only in XML response. Also, when the value is null, the element shouldn't show up in the response for both formats.
Expectation:
XML:
<name>john</name>
<status type="text">married</status>
JSON:
"name":"john"
"status":"married"
This is my code:
/**
* POJO with bunch of LOMBOK annotations to avoid boiler-plate code.
*/
#AllArgsConstructor
#NoArgsConstructor
#Builder(toBuilder = true)
#Data
public class User implements Customer, Serializable {
private static final long serialVersionUID = 1L;
private Status status;
private String name;
/**
* Matrital status of the user.
*/
#Builder
#Value
public static class Status {
#JacksonXmlText
private String maritalStatus;
#JacksonXmlProperty(isAttribute = true)
private String type = "text";
}
}
With the above change, I am getting the correct XML response but JSON response also returns type=text
"status" : {
"maritalStatus" : "married",
"type" : "text"
}
I tried to add #JsonValue to private String maritalStatus, that solved the JSON response but it broke XML response by not adding the attribute to the element.
Can someone please help?
Probably the easiest way is to implement custom serialiser for User.Status and produce different output for different kinds of representation.
class UserStatusJsonSerializer extends JsonSerializer<User.Status> {
#Override
public void serialize(User.Status value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (gen instanceof ToXmlGenerator) {
ToXmlGenerator toXmlGenerator = (ToXmlGenerator) gen;
serializeXml(value, toXmlGenerator);
} else {
gen.writeString(value.getMaritalStatus());
}
}
private void serializeXml(User.Status value, ToXmlGenerator toXmlGenerator) throws IOException {
toXmlGenerator.writeStartObject();
toXmlGenerator.setNextIsAttribute(true);
toXmlGenerator.writeFieldName("type");
toXmlGenerator.writeString(value.getType());
toXmlGenerator.setNextIsAttribute(false);
toXmlGenerator.writeRaw(value.getMaritalStatus());
toXmlGenerator.writeEndObject();
}
#Override
public boolean isEmpty(SerializerProvider provider, User.Status value) {
return value == null || value.getMaritalStatus() == null;
}
}
Since now, you can remove extra XML annotations and register custom serialiser:
#AllArgsConstructor
#NoArgsConstructor
#Builder(toBuilder = true)
#Data
class User implements Serializable {
private static final long serialVersionUID = 1L;
private Status status;
private String name;
#Builder
#Value
#JsonSerialize(using = UserStatusJsonSerializer.class)
public static class Status {
private String maritalStatus;
private String type = "text";
}
}
Simple console app usage could look like below:
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Value;
import java.io.IOException;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
public class JsonPathApp {
public static void main(String[] args) throws Exception {
List<User> users = Arrays.asList(
createUser("John", "married"),
createUser("Tom", null));
ObjectMapper jsonMapper = JsonMapper.builder()
.enable(SerializationFeature.INDENT_OUTPUT)
.serializationInclusion(JsonInclude.Include.NON_EMPTY)
.build();
for (User user : users) {
System.out.println(jsonMapper.writeValueAsString(user));
System.out.println();
}
XmlMapper xmlMapper = XmlMapper.builder()
.enable(SerializationFeature.INDENT_OUTPUT)
.serializationInclusion(JsonInclude.Include.NON_EMPTY)
.build();
for (User user : users) {
System.out.println(xmlMapper.writeValueAsString(user));
System.out.println();
}
}
private static User createUser(String name, String maritalStatus) {
return User.builder()
.name(name)
.status(User.Status.builder()
.maritalStatus(maritalStatus)
.build())
.build();
}
}
Above code prints
JSON for John:
{
"status" : "married",
"name" : "John"
}
JSON for Tom:
{
"name" : "Tom"
}
XML for John:
<User>
<status type="text">married</status>
<name>John</name>
</User>
XML for Tom
<User>
<name>Tom</name>
</User>
Notice, that we implemented UserStatusJsonSerializer#isEmpty method which defines what empty means for a Status class. Now, we need to enable JsonInclude.Include.NON_EMPTY feature in your Spring Boot application. Add below key to your application configuration file:
spring.jackson.default-property-inclusion=non_empty
If you do not want to enable inclusion globally you can enable it only for one property using #JsonInclude annotation.
#JsonInclude(JsonInclude.Include.NON_EMPTY)
private Status status;
See also:
Using Jackson to add XML attributes to manually-built node-tree
How to tell Jackson to ignore a field during serialization if its value is null?
Spring Boot: Customize the Jackson ObjectMapper
The solution to marshalling an object one way in XML, but another in JSON (different fields, etc.) was to use "mixins".
One trick is that you have to manually register the mixin, there's no magic. See below.
Mixin interface:
public interface UserStatusXmlMixin {
#JsonValue(false)
#JacksonXmlText
String getStatus();
#JacksonXmlProperty(isAttribute = true)
String getType();
}
Implementation:
#Value
public class UserStatus implements UserStatusXmlMixin {
private String status;
#JsonValue
#Override
public String getStatus() {
return status;
}
#Override
public String getType() {
return "text";
}
/**
* Returns an unmodifiable UserStatus when status is available,
* otherwise return null. This will help to remove this object from the responses.
*/
public static UserStatus of(final String status) {
return Optional.ofNullable(status)
.map(UserStatus::new)
.orElse(null);
}
}
I also had to register the "mixin" manually.
#Configuration
public class AppJacksonModule extends SimpleModule {
private static final long serialVersionUID = -1;
private final Map<Class, Class> mixinByTarget;
/**
* Construct an AppJacksonModule.
*/
public AppJacksonModule() {
super("AppJacksonModule");
this.mixinByTarget = Map.of(
UserStatus.class, UserStatusXmlMixin.class
);
}
#Override
public void setupModule(final SetupContext context) {
super.setupModule(context);
final ObjectCodec contextOwner = context.getOwner();
if (contextOwner instanceof XmlMapper) {
mixinByTarget.forEach(context::setMixInAnnotations);
}
}
Now wherever I needed to create UserStatus using UserStatus.of(..) if the input param is null, <status/> won't show up in the response.

how to add custom objectMapper for a specific spring rest controller

I have two controllers in my micro service both are POST and accepts Request body as JSON, one is working fine and another one's JSON input from some othet team and it is with root class name , so I need to write custom object mapper for this later controller, could you please guys help,
please find the codes below,
#RestController
#Slf4j
public class Controller2 {
#RequestMapping(value = "/some/update", method = RequestMethod.POST)
public String updateEmd(#RequestBody final UpdateEMDRequest updateEMDRequest) throws JsonProcessingException {
updateEMDRequest.getBookingReference()); // null now
return "success";
}
}
and the sample json is as follows,
{
"UpdateEMDRequest":{
"TransactionStatus":"SUCCESS",
"UniqueTransactionReference":"046060420",
"PreAuthReference":"040520420",
"BookingReference":"8PJ",
"CarrierCode":"AS",
"TransactionMode":"Batch",
"CallBackUrl":"www.test.com/op/update",
"Offers":[
{
"Offer":{
"traveler":{
"firstName":"AHONY",
"surname":"DNEN",
"EMD":[
"081820470"
]
}
}
}
]
}
}
UpdateEMDRequest,java
#JsonInclude(Include.NON_NULL)
public class UpdateEMDRequest {
#JsonProperty("UniqueTransactionReference")
private String uniqueTransactionReference;
#JsonProperty("TransactionStatus")
private String transactionStatus;
#JsonProperty("PreAuthReference")
private String preAuthReference;
#JsonProperty("BookingReference")
private String bookingReference;
#JsonProperty("CarrierCode")
private String carrierCode;
#JsonProperty("TransactionMode")
private String transactionMode;
#JsonProperty("CallBackUrl")
private String callBackUrl;
#JsonProperty("Offers")
private List<Offers> offers;
}
So this json is not parsed properly and updateEMDRequest's properties are null always.

GSON deserialize POJO with root value included

I would like to achieve the opposite of this:
Gson serialize POJO with root value included?
I get a JSON String
{"RootDTO":{"classField_01":"value"}}
and would like to deserialise that to
class RootDTO {
String classField_01;
//nice getter and setter are included
}
I know how to set the parameter so that in serialisation the root element is included into the JSON string.
But how to deserialise that now? Searching like hell already but wasn't able to find a suitable answer.
Thank you for any ideas!
make RootDTO.java
import com.google.gson.annotations.SerializedName;
public class RootDTO {
#SerializedName("classField_01")
private String classField_01;
public String getClassField_01() {
return classField_01;
}
public void setClassField_01(String classField_01) {
this.classField_01 = classField_01;
}
}
make Response.java
import com.google.gson.annotations.SerializedName;
public class Response {
#SerializedName("RootDTO")
private RootDTO rootDTO;
public RootDTO getRootDTO() {
return rootDTO;
}
public void setRootDTO(RootDTO rootDTO) {
this.rootDTO = rootDTO;
}
}
test this code to generate your json data
import com.google.gson.Gson;
public class TestOne {
public static void main(String[] args) {
RootDTO dto = new RootDTO();
dto.setClassField_01("value");
Response response = new Response();
response.setRootDTO(dto);
String result = (new Gson()).toJson(response);
System.out.println(""+result);
}
}
output generated with this code
{"RootDTO":{"classField_01":"value"}}

Modify default JSON error response from Spring Boot Rest Controller

Currently the error response from spring boot contains the standard content like below:
{
"timestamp" : 1426615606,
"exception" : "org.springframework.web.bind.MissingServletRequestParameterException",
"status" : 400,
"error" : "Bad Request",
"path" : "/welcome",
"message" : "Required String parameter 'name' is not present"
}
I am looking for a way to get rid of the "exception" property in the response. Is there a way to achieve this?
As described in the documentation on error handling, you can provide your own bean that implements ErrorAttributes to take control of the content.
An easy way to do that is to subclass DefaultErrorAttributes. For example:
#Bean
public ErrorAttributes errorAttributes() {
return new DefaultErrorAttributes() {
#Override
public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) {
Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace);
// Customize the default entries in errorAttributes to suit your needs
return errorAttributes;
}
};
}
If there is empty message text in json when you encounter exception, you can be hit by changed behavior in spring boot 2.3.0. If this is the case, just change your server.error.include-message property to always.
Following answer is totally derived from Andy Wilkinson's answer (which uses web.reactive classes)
- It includes web.servlet based classes.
- Spring boot 2.2.4.RELEASE
ExceptionHandlerConfig.java
package com.example.sample.core.exception;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.WebRequest;
#Configuration
public class ExceptionHandlerConfig {
//private static final String DEFAULT_KEY_TIMESTAMP = "timestamp";
private static final String DEFAULT_KEY_STATUS = "status";
private static final String DEFAULT_KEY_ERROR = "error";
private static final String DEFAULT_KEY_ERRORS = "errors";
private static final String DEFAULT_KEY_MESSAGE = "message";
//private static final String DEFAULT_KEY_PATH = "path";
public static final String KEY_STATUS = "status";
public static final String KEY_ERROR = "error";
public static final String KEY_MESSAGE = "message";
public static final String KEY_TIMESTAMP = "timestamp";
public static final String KEY_ERRORS = "errors";
//
#Bean
public ErrorAttributes errorAttributes() {
return new DefaultErrorAttributes() {
#Override
public Map<String ,Object> getErrorAttributes(
WebRequest webRequest
,boolean includeStackTrace
) {
Map<String ,Object> defaultMap
= super.getErrorAttributes( webRequest ,includeStackTrace );
Map<String ,Object> errorAttributes = new LinkedHashMap<>();
// Customize.
// For eg: Only add the keys you want.
errorAttributes.put( KEY_STATUS, defaultMap.get( DEFAULT_KEY_STATUS ) );
errorAttributes.put( KEY_MESSAGE ,defaultMap.get( DEFAULT_KEY_MESSAGE ) );
return errorAttributes;
}
};
}
}

how do i create data in json format

I have a Struts 2 application in which i use the struts 2 json plugin for json handling.
Now i want to use the dojo data grid to populate data from an action. I can call the action. All the inbuilt data types are working in the action. However when i use a custom object in my class, i get errors in the action class.
I want to use ItemFileReadStore as a store for the grid which needs data in the format like:
items: [{obj1},{obj2},{obj3},{obj4}]
Now i have a class called Device. I want to send a list of Device objects back to the client. But how do i provide data in the above format and use it on client side.?
Edit:
I get the following error:
E com.ibm.ws.webcontainer.webapp.WebApp logError SRVE0293E: [Servlet Error]-[com.googlecode.jsonplugin.JSONException: com.googlecode.jsonplugin.JSONException: java.lang.reflect.InvocationTargetException]: com.ibm.ws.webcontainer.webapp.WebAppErrorReport: com.googlecode.jsonplugin.JSONException: com.googlecode.jsonplugin.JSONException: java.lang.reflect.InvocationTargetException
at com.ibm.ws.webcontainer.webapp.WebAppDispatcherContext.sendError(WebAppDispatcherContext.java:624)
at com.ibm.ws.webcontainer.srt.SRTServletResponse.sendError(SRTServletResponse.java:1071)
at org.apache.struts2.dispatcher.Dispatcher.sendError(Dispatcher.java:725)
at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:485)
at org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:395)
at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:188)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:116)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:77)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:852)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:917)
at com.ibm.ws.webcontainer.extension.DefaultExtensionProcessor.invokeFilters(DefaultExtensionProcessor.java:924)
at com.ibm.ws.webcontainer.extension.DefaultExtensionProcessor.handleRequest(DefaultExtensionProcessor.java:852)
at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3610)
at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:274)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:926)
at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1557)
at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:173)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:455)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:384)
at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:83)
at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:202)
at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:766)
at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:896)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1527)
What is the reason for this error. My action class is:
jsonWrapper.setIdentifier("firstName");
jsonWrapper.getListItems().add(User.getUser("t2590pk"));
jsonWrapper.getListItems().add(User.getUser("t8923sm"));
jsonWrapper.setItems(jsonWrapper.gson.toJson(jsonWrapper.getListItems()));
System.out.println(jsonWrapper.getItems());
Struts config:
<action name="jsonTest" class="com.dcx.ispeed.actions.JSONTest">
<result type="json">
<param name="excludeProperties">
gson
</param>
</result>
</action>
The jsonWrapper class:
/**
*
*/
package com.dcx.ispeed.business;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.gson.Gson;
import com.ibm.ws.http.HttpRequest;
/**
* #author t2590pk
*
*/
public class JSONWrapper {
public Gson gson = new Gson();
private String identifier;
private String label;
private String items;
private List listItems = new ArrayList();
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getItems() {
return items;
}
public void setItems(String items) {
this.items = items;
}
public List getListItems() {
return listItems;
}
public void setListItems(List listItems) {
this.listItems = listItems;
}
/**
*
*/
public JSONWrapper() {
System.out.println("Calling JSON wrapper constructor.");
}
}
Thanks.. :)
You can use google Gson package as following
import com.google.gson.Gson;
String json = "{\"name\":\"ABC\",\"address\":\"some address\"}";
Gson gson = new Gson();
Person person = gson.fromJson(json, Person.class);
public class Person{
public String name;
public String address;
}
Note: you have to implement default constructor and all getter and setter for the Person class.
The array in your case will be a Set
this might be happen with your gson library so please update your gson library and etends jsonException when u use json that will show where in your code exception is coming.