#RequestMapping(value = "/check", method = RequestMethod.GET)
public ResponseEntity<Product> createProducts() throws JsonProcessingException {
String reqUrl = "http://localhost:8080/home";
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
Map<String, String> bodyParamMap = new HashMap<String, String>();
bodyParamMap.put("grant_type", "K1");
bodyParamMap.put("client_id", "K2");
bodyParamMap.put("client_secret", "sjxjkdcnjkk");
String reqBodyData = new ObjectMapper().writeValueAsString(bodyParamMap);
HttpEntity<String> requestEnty = new HttpEntity<>(reqBodyData, headers);
ResponseEntity<Product> result = restTemplate.postForEntity(reqUrl, requestEnty, Product.class);
return result;
}
I am geeting a JSON response form result which have access_token which I want to get.
I tried using JSONObject but it is not working. How Can I fetch the value of access_token
JSONObject jsonObject = JSONObject.fromObject(result.toString());
String m = jsonObject.get("access_token").toString();
I tried using this but it is showing compile time error
My output is accepted as
{"access_token":"ghdjhdjhhh","expires_in":2300}
I want to fetch this access_token
when you use postForEntity your Product.class is suppose to represent your result (responseType), so if your converters are well defined(normally the spring boot default ones are sufficient for json) with your class Product looking like this
public class Product {
#JsonProperty("access_token")
private String accessToken;
#JsonProperty("expires_in")
private Long expiresIn;
public String getAccessToken() {
return accessToken;
}
public Long getExpiresIn() {
return expiresIn;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public void setExpiresIn(Long expiresIn) {
this.expiresIn = expiresIn;
}
}
then you can get your result like this
ResponseEntity<Product> result = restTemplate.postForEntity(reqUrl, requestEnty, Product.class);
Product product = result.getBody();
String token = product.getAccessToken()
I have a RestController and when I call the method:
#RequestMapping(value = "/sigla/{sigla}")
#ResponseBody
public PaisDTO obterPorSigla(#PathVariable String sigla) {
return service.obterPorSigla(sigla);
}
If a record is found, I get a good JSON response:
{"nome":"Brasil","sigla":"BR","quantidadeEstados":27}
but when nothing is found on database the RestController returns null and I get a empty response, completely blank body.
How can I display a empty JSON instead of a blank response? Like bellow:
{}
Complete Controller:
#RestController
#RequestMapping("/pais")
public class PaisController {
#Autowired
private PaisService service;
#RequestMapping
public ResponseEntity<List<PaisDTO>> obterTodos() {
return CreateResponseEntity.getResponseEntity(service.obterTodos());
}
#RequestMapping(value = "/sigla/{sigla}", method = RequestMethod.GET, consumes="application/json", produces="application/json")
public ResponseEntity<PaisDTO> obterPorSigla(#PathVariable String sigla) {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
PaisDTO paisDTO = service.obterPorSigla(sigla);
if(paisDTO != null) return new ResponseEntity<PaisDTO>(paisDTO, headers, HttpStatus.OK);
else return new ResponseEntity<PaisDTO>(headers, HttpStatus.OK);
}
Solution 1:
You have to implement you entity class with Serializable
Solution 2:
Your class should have getter and setter
In my case the getter and setter were given protected access modifiers. so I changed them to public and vola it worked
First, if you're using #RestController annotation you don't need the #ResponseBody annotation, get rid of that.
Second if you're trying to have REST Controller, then you're missing a few things, do it like this:
#RequestMapping(value = "/sigla/{sigla}", method = RequestMethod.GET, consumes = "application/json", produces="application/json")
public ResponseEntity<PaisDTO> obterPorSigla(#PathVariable String sigla) {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
PaisDTO paisDTO = service.obterPorSigla(sigla);
if(paisDTO != null) return new ResponseEntity<>(paisDTO, headers, HttpStatus.OK);
else return new ResponseEntity<>(headers, HttpStatus.OK);
}
In the example above if you'll get null then you'll return an empty response JSON.
The only way that I could find was to create an empty class
#JsonSerialize
public class EmptyJsonBody {
}
Then add this to your response
#PostMapping(value = "/sigla/{sigla}")
public ResponseEntity obterPorSigla(#PathVariable String sigla) {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json");
PaisDTO paisDTO = service.obterPorSigla(sigla);
ResponseEntity.BodyBuilder responseBuilder = ResponseEntity.ok().headers(headers);
if(paisDTO != null) {
return responseBuilder.body(paisDTO);
} else {
return responseBuilder.body(new EmptyJsonBody());
}
}
I am trying to pass a parameter which is the userID and then get the response in the form of the JSON.
So if userID=1 then the response would be
[{"carname":"Honda","carmodel":"Civic"}]
and if userID=5then the response would be
[{"carname":"Honda","carmodel":"Civic"},{"carname":"VW","carmodel":"Golf"},{"carname":"Ford","carmodel":"Focus"}]
But for some reason, the parameters are not being passed and if they are then I am unable to retrieve values in JSON
This is my code below:
public void getComments(int userID){
String passURL = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest
(passURL, new Response.Listener<JSONArray>(){
#Override
public void onResponse(JSONArray jsonArray) {
try {
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String carName = jsonObject.getString("carname");
String carModel = jsonObject.getString("carmodel");
UserStore userStore = new UserStore(carName, carModel);
list.add(userStore);
adapter.notifyDataSetChanged();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
}
}) {
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
params.put("userID", Integer.toString(userID));
return params;
}
};
requestQueue.add(jsonArrayRequest);
}
I suspect it something to do with the fact that I am trying to get the response from the array after passing a parameter. My php works in Postman
Using mcxiaoke library version 1.0.14 and above
JsonArrayRequest
You need to set the Method as Post in JsonArrayRequest as like below
JsonArrayRequest jsonArrReq = new JsonArrayRequest(Method.POST,
url, null,new Response.Listener<JSONArray>()
{
......
//onResponse
......
}
getParams()
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("user", "Android");
return params;
}
I am writing a rest service using spring MVC which produces JSON response. It should allow client to select only the given fields in response, means client can mention the fields he is interested in as url parameter like ?fields=field1,field2.
Using Jackson annotations does not provide what I am looking for as it is not dynamic also the filters in Jackson doesnt seem to be promising enough.
So far I am thinking to implement a custom message converter which can take care of this.
Is there any other better way to achieve this? I would like if this logic is not coupled with my services or controllers.
From Spring 4.2, #JsonFilter is supported in MappingJacksonValue
Issue : SPR-12586 : Support Jackson #JsonFilter
Commit : ca06582
You can directly inject PropertyFilter to MappingJacksonValue in a controller.
#RestController
public class BookController {
private static final String INCLUSION_FILTER = "inclusion";
#RequestMapping("/novels")
public MappingJacksonValue novel(String[] include) {
#JsonFilter(INCLUSION_FILTER)
class Novel extends Book {}
Novel novel = new Novel();
novel.setId(3);
novel.setTitle("Last summer");
novel.setAuthor("M.K");
MappingJacksonValue res = new MappingJacksonValue(novel);
PropertyFilter filter = SimpleBeanPropertyFilter.filterOutAllExcept(include);
FilterProvider provider = new SimpleFilterProvider().addFilter(INCLUSION_FILTER, filter);
res.setFilters(provider);
return res;
}
or you can declare global policy by ResponseBodyAdvice. The following example implements filtering policy by "exclude" parameter.
#ControllerAdvice
public class DynamicJsonResponseAdvice extends AbstractMappingJacksonResponseBodyAdvice {
public static final String EXCLUDE_FILTER_ID = "dynamicExclude";
private static final String WEB_PARAM_NAME = "exclude";
private static final String DELI = ",";
private static final String[] EMPTY = new String[]{};
#Override
protected void beforeBodyWriteInternal(MappingJacksonValue container, MediaType contentType,
MethodParameter returnType, ServerHttpRequest req, ServerHttpResponse res) {
if (container.getFilters() != null ) {
// It will be better to merge FilterProvider
// If 'SimpleFilterProvider.addAll(FilterProvider)' is provided in Jackson, it will be easier.
// But it isn't supported yet.
return;
}
HttpServletRequest baseReq = ((ServletServerHttpRequest) req).getServletRequest();
String exclusion = baseReq.getParameter(WEB_PARAM_NAME);
String[] attrs = StringUtils.split(exclusion, DELI);
container.setFilters(configFilters(attrs));
}
private FilterProvider configFilters(String[] attrs) {
String[] ignored = (attrs == null) ? EMPTY : attrs;
PropertyFilter filter = SimpleBeanPropertyFilter.serializeAllExcept(ignored);
return new SimpleFilterProvider().addFilter(EXCLUDE_FILTER_ID, filter);
}
}
IMHO, the simplest way to do that would be to use introspection to dynamically generate a hash containing selected fields and then serialize that hash using Json. You simply have to decide what is the list of usable fields (see below).
Here are two example functions able to do that, first gets all public fields and public getters, the second gets all declared fields (including private ones) in current class and all its parent classes :
public Map<String, Object> getPublicMap(Object obj, List<String> names)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
List<String> gettedFields = new ArrayList<String>();
Map<String, Object> values = new HashMap<String, Object>();
for (Method getter: obj.getClass().getMethods()) {
if (getter.getName().startsWith("get") && (getter.getName().length > 3)) {
String name0 = getter.getName().substring(3);
String name = name0.substring(0, 1).toLowerCase().concat(name0.substring(1));
gettedFields.add(name);
if ((names == null) || names.isEmpty() || names.contains(name)) {
values.put(name, getter.invoke(obj));
}
}
}
for (Field field: obj.getClass().getFields()) {
String name = field.getName();
if ((! gettedFields.contains(name)) && ((names == null) || names.isEmpty() || names.contains(name))) {
values.put(name, field.get(obj));
}
}
return values;
}
public Map<String, Object> getFieldMap(Object obj, List<String> names)
throws IllegalArgumentException, IllegalAccessException {
Map<String, Object> values = new HashMap<String, Object>();
for (Class<?> clazz = obj.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) {
for (Field field : clazz.getDeclaredFields()) {
String name = field.getName();
if ((names == null) || names.isEmpty() || names.contains(name)) {
field.setAccessible(true);
values.put(name, field.get(obj));
}
}
}
return values;
}
Then you only have to get the result of one of this function (or of one you could adapt to your requirements) and serialize it with Jackson.
If you have custom encoding of you domain objects, you would have to maintain the serialization rules in two different places : hash generation and Jackson serialization. In that case, you could simply generate the full class serialization with Jackson and filter the generated string afterwards. Here is an example of such a filter function :
public String jsonSub(String json, List<String> names) throws IOException {
if ((names == null) || names.isEmpty()) {
return json;
}
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> map = mapper.readValue(json, HashMap.class);
for (String name: map.keySet()) {
if (! names.contains(name)) {
map.remove(name);
}
}
return mapper.writeValueAsString(map);
}
Edit : integration in Spring MVC
As you are speaking of a web service and of Jackson, I assume that you use Spring RestController or ResponseBody annotations and (under the hood) a MappingJackson2HttpMessageConverter. If you use Jackson 1 instead, it should be a MappingJacksonHttpMessageConverter.
What I propose is simply to add a new HttpMessageConverter that could make use of one of the above filtering functions, and delegate actual work (and also ancilliary methods) to a true MappingJackson2HttpMessageConverter. In the write method of that new converter, it is possible to have access to the eventual fields request parameter with no need for an explicit ThreadLocal variable thanks to Spring RequestContextHolder. That way :
you keep a clear separation of roles with no modification on existing controllers
you have no modification in Jackson2 configuration
you need no new ThreadLocal variable and simply use a Spring class in a class already tied to Spring since it implements HttpMessageConverter
Here is an example of such a message converter :
public class JsonConverter implements HttpMessageConverter<Object> {
private static final Logger logger = LoggerFactory.getLogger(JsonConverter.class);
// a real message converter that will respond to ancilliary methods and do the actual work
private HttpMessageConverter<Object> delegate =
new MappingJackson2HttpMessageConverter();
// allow configuration of the fields name
private String fieldsParam = "fields";
public void setFieldsParam(String fieldsParam) {
this.fieldsParam = fieldsParam;
}
#Override
public boolean canRead(Class<?> clazz, MediaType mediaType) {
return delegate.canRead(clazz, mediaType);
}
#Override
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
return delegate.canWrite(clazz, mediaType);
}
#Override
public List<MediaType> getSupportedMediaTypes() {
return delegate.getSupportedMediaTypes();
}
#Override
public Object read(Class<? extends Object> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
return delegate.read(clazz, inputMessage);
}
#Override
public void write(Object t, MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
// is there a fields parameter in request
String[] fields = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest().getParameterValues(fieldsParam);
if (fields != null && fields.length != 0) {
// get required field names
List<String> names = new ArrayList<String>();
for (String field : fields) {
String[] f_names = field.split("\\s*,\\s*");
names.addAll(Arrays.asList(f_names));
}
// special management for Map ...
if (t instanceof Map) {
Map<?, ?> tmap = (Map<?, ?>) t;
Map<String, Object> map = new LinkedHashMap<String, Object>();
for (Entry entry : tmap.entrySet()) {
String name = entry.getKey().toString();
if (names.contains(name)) {
map.put(name, entry.getValue());
}
}
t = map;
} else {
try {
Map<String, Object> map = getMap(t, names);
t = map;
} catch (Exception ex) {
throw new HttpMessageNotWritableException("Error in field extraction", ex);
}
}
}
delegate.write(t, contentType, outputMessage);
}
/**
* Create a Map by keeping only some fields of an object
* #param obj the Object
* #param names names of the fields to keep in result Map
* #return a map containing only requires fields and their value
* #throws IllegalArgumentException
* #throws IllegalAccessException
*/
public static Map<String, Object> getMap(Object obj, List<String> names)
throws IllegalArgumentException, IllegalAccessException {
Map<String, Object> values = new HashMap<String, Object>();
for (Class<?> clazz = obj.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) {
for (Field field : clazz.getDeclaredFields()) {
String name = field.getName();
if (names.contains(name)) {
field.setAccessible(true);
values.put(name, field.get(obj));
}
}
}
return values;
}
}
If you want the converter to be more versatile, you could define an interface
public interface FieldsFilter {
Map<String, Object> getMap(Object obj, List<String> names)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;
}
and inject it with an implementation of that.
Now you must ask Spring MVC to use that custom message controller.
If you use XML config, you simply declare it in the <mvc:annotation-driven> element :
<mvc:annotation-driven >
<mvc:message-converters>
<bean id="jsonConverter" class="org.example.JsonConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
And if you use Java configuration, it is almost as simple :
#EnableWebMvc
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Autowired JsonConverter jsonConv;
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(jsonConv);
StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
stringConverter.setWriteAcceptCharset(false);
converters.add(new ByteArrayHttpMessageConverter());
converters.add(stringConverter);
converters.add(new ResourceHttpMessageConverter());
converters.add(new SourceHttpMessageConverter<Source>());
converters.add(new AllEncompassingFormHttpMessageConverter());
converters.add(new MappingJackson2HttpMessageConverter());
}
}
but here you have to explicitely add all the default message converters that you need.
I've never done this but after looking at this page http://wiki.fasterxml.com/JacksonFeatureJsonFilter it seems that it would be possible to do what you want this way:
1) Create a custom JacksonAnnotationIntrospector implementation (by extending default one) that will use a ThreadLocal variable to choose a filter for current request and also create a custom FilterProvider that would provide that filter.
2) Configure the message converter's ObjectMapper to use the custom introspector and filter provider
3) Create an MVC interceptor for REST service that detects fields request parameter and configures a new filter for current request via your custom filter provider (this should be a thread local filter). ObjectMapper should pick it up through your custom JacksonAnnotationIntrospector.
I'm not 100% certain that this solution would be thread safe (it depends on how ObjectMapper uses annotation introspector and filter provider internally).
- EDIT -
Ok I did a test implementation and found out that step 1) wouldn't work because Jackson caches the result of AnnotationInterceptor per class. I modified idea to apply dynamic filtering only on annotated controller methods and only if the object doesn't have anoter JsonFilter already defined.
Here's the solution (it's quite lengthy):
DynamicRequestJsonFilterSupport class manages the per-request fields to be filtered out:
public class DynamicRequestJsonFilterSupport {
public static final String DYNAMIC_FILTER_ID = "___DYNAMIC_FILTER";
private ThreadLocal<Set<String>> filterFields;
private DynamicIntrospector dynamicIntrospector;
private DynamicFilterProvider dynamicFilterProvider;
public DynamicRequestJsonFilterSupport() {
filterFields = new ThreadLocal<Set<String>>();
dynamicFilterProvider = new DynamicFilterProvider(filterFields);
dynamicIntrospector = new DynamicIntrospector();
}
public FilterProvider getFilterProvider() {
return dynamicFilterProvider;
}
public AnnotationIntrospector getAnnotationIntrospector() {
return dynamicIntrospector;
}
public void setFilterFields(Set<String> fieldsToFilter) {
filterFields.set(Collections.unmodifiableSet(new HashSet<String>(fieldsToFilter)));
}
public void setFilterFields(String... fieldsToFilter) {
filterFields.set(Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(fieldsToFilter))));
}
public void clear() {
filterFields.remove();
}
public static class DynamicIntrospector extends JacksonAnnotationIntrospector {
#Override
public Object findFilterId(Annotated annotated) {
Object result = super.findFilterId(annotated);
if (result != null) {
return result;
} else {
return DYNAMIC_FILTER_ID;
}
}
}
public static class DynamicFilterProvider extends FilterProvider {
private ThreadLocal<Set<String>> filterFields;
public DynamicFilterProvider(ThreadLocal<Set<String>> filterFields) {
this.filterFields = filterFields;
}
#Override
public BeanPropertyFilter findFilter(Object filterId) {
return null;
}
#Override
public PropertyFilter findPropertyFilter(Object filterId, Object valueToFilter) {
if (filterId.equals(DYNAMIC_FILTER_ID) && filterFields.get() != null) {
return SimpleBeanPropertyFilter.filterOutAllExcept(filterFields.get());
}
return super.findPropertyFilter(filterId, valueToFilter);
}
}
}
JsonFilterInterceptor intercepts controller methods annotated with custom #ResponseFilter annotation.
public class JsonFilterInterceptor implements HandlerInterceptor {
#Autowired
private DynamicRequestJsonFilterSupport filterSupport;
private ThreadLocal<Boolean> requiresReset = new ThreadLocal<Boolean>();
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod method = (HandlerMethod) handler;
ResponseFilter filter = method.getMethodAnnotation(ResponseFilter.class);
String[] value = filter.value();
String param = filter.param();
if (value != null && value.length > 0) {
filterSupport.setFilterFields(value);
requiresReset.set(true);
} else if (param != null && param.length() > 0) {
String filterParamValue = request.getParameter(param);
if (filterParamValue != null) {
filterSupport.setFilterFields(filterParamValue.split(","));
}
}
}
requiresReset.remove();
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
Boolean reset = requiresReset.get();
if (reset != null && reset) {
filterSupport.clear();
}
}
}
Here's the custom #ResponseFilter annotation. You can either define a static filter (via annotation's value property) or a filter based on request param (via annotation's param property):
#Target({ElementType.METHOD, ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
public #interface ResponseFilter {
String[] value() default {};
String param() default "";
}
You will need to setup the message converter and the interceptor in the config class:
...
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(converter());
}
#Bean
JsonFilterInterceptor jsonFilterInterceptor() {
return new JsonFilterInterceptor();
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jsonFilterInterceptor);
}
#Bean
DynamicRequestJsonFilterSupport filterSupport() {
return new DynamicRequestJsonFilterSupport();
}
#Bean
MappingJackson2HttpMessageConverter converter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper();
mapper.setAnnotationIntrospector(filterSupport.getAnnotationIntrospector());
mapper.setFilters(filterSupport.getFilterProvider());
converter.setObjectMapper(mapper);
return converter;
}
...
And finally, you can use the filter like this:
#RequestMapping("/{id}")
#ResponseFilter(param = "fields")
public Invoice getInvoice(#PathVariable("id") Long id) { ... }
When request is made to /invoices/1?fields=id,number response will be
filtered and only id and number properties will be returned.
Please note I haven't tested this thoroughly but it should get you started.
Would populating a HashMap from the object not suite the requirements? You could then just parse the HashMap. I have done something similar with GSON in the past where I had to provide a simple entity and ended up just populating a HashMap and then serializing it, it was far more maintainable than over engineering a whole new system.
I have a Java class in a servlet that uses GSON to render posted JSON Strings into a Java object. The beauty of the approach is, that GSON filters out all JSON elements that don't match a class property, so I never end up with JSON content that I don't want to process. The servlet's doPost (simplified) looks like this:
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
PrintWriter out = null;
try {
InputStream in = request.getInputStream();
Demo d = Demo.load(in);
in.close();
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_OK);
out = response.getWriter();
out.println(d.toJson);
} catch (Exception e) {
e.printStackTrace();
out.println(e.getMessage());
}
out.close();
}
The Demo class (and that's the one I need to recreate in common.js or node.js looks like this:
#JsonIgnoreProperties(ignoreUnknown = true)
public class Demo implements Serializable {
public static Demo load(InputStream in) {
Demo result = null;
try {
Gson gson = new GsonBuilder().create();
result = gson.fromJson(new InputStreamReader(in), Demo.class);
} catch (Exception e) {
result = null;
}
return result;
}
#TypeDiscriminator
#JsonProperty("_id")
private String id = UUID.randomUUID().toString();
private Date created = new Date();
private String color;
private String name;
private String taste;
public String getColor() {
return this.color;
}
public String getName() {
return this.name;
}
public String getTaste() {
return this.taste;
}
public Date getCreated() {
return this.created;
}
public String getId() {
return this.id;
}
public void setName(String name) {
this.name = name;
}
public void setTaste(String taste) {
this.taste = taste;
}
public void setColor(String color) {
this.color = color;
}
public String toJson() {
GsonBuilder gb = new GsonBuilder();
gb.setPrettyPrinting();
gb.disableHtmlEscaping();
Gson gson = gb.create();
return gson.toJson(this);
}
}
Obviously I stripped out all the processing logic and the servlet just echos the JSON back, which is not what the app does, but serves to illustrate the point. I can throw pretty any String in a HTTP Post at that example and I only get valid Demo objects.
How would I do something like this in node.js?
Node.js is Javascript so has built in support for json. You can use JSON.parse to convert from string to json and wrap in try catch block.
To only include select properties there is no built in feature in node that I know of unless you are using Mongodb with mongoose, but you could do following: Have a "class" that is an object containing all properties that you want and delete those from parsed json object that are not in that "class" object.
var class = {x: null, y:null};
for(var prop in object){
if (!class.hasOwnProperty (prop)) {
delete object [prop]
}
It would be best to use this class as object and expose parseJSON function to encapsulate this functionality