Why isn't cxf json marshaing fields with null value - json

cxf version 2.2.7.
json string only contains not null value, but not contains null value properties, e.g.:
class Bean {String field1;String field2}
Bean bean = new Bean();
bean.setField1("value1");
after marshaing, result json is:
{"field1":"value1"}
I expect json to be:
{"field1":"value1","field2":""}
Thanks !

As far as I know it is not possible to map null values in Jettison (default JSON provider). However, if you switch to Jackson then you get what you want. Jackson maps null values to null.
In order to achieve that add the following maven dependency:
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>1.9.0</version>
</dependency>
And replace org.apache.cxf.jaxrs.provider.json.JSONProvider with org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider.
The result is:
{"field1":"value1","field2":null}

Related

How to use default values of Kotlin (1.4.21) data class in Jackson (2.12.0) and Quarkus (1.11.1)

I am using Quarkus 1.11.1 with Kotlin 1.4.21 and Jackson 2.12.0.
I don't understand why when I send a POST request with a body of a data class that has a defined default parameter, this is not accepted and returns an error problem: Parameter specified as non-null is null
In the pom.xml file I have:
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-kotlin</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jackson</artifactId>
</dependency>
The Quarkus Documentation says (https://quarkus.io/guides/kotlin#kotlin-and-jackson):
If the com.fasterxml.jackson.module:jackson-module-kotlin dependency and the quarkus-jackson extension (or the quarkus-resteasy-extension) have been added to project, then Quarkus automatically registers the KotlinModule to the ObjectMapper bean (see this guide for more details).
I have a data class like:
data class MyAttributes
#BsonCreator constructor(
#BsonProperty("myId")
#JsonProperty("myId")
var myId: String,
#BsonProperty("name")
#JsonProperty("name")
val name: String,
#BsonProperty("data")
#JsonProperty("data", defaultValue = "{}")
var data: MutableMap<String, Any> = mutableMapOf()
)
I noticed that the defaultValue in the #JsonProperty annotation is not useful, because it is used only to document expected values (https://fasterxml.github.io/jackson-annotations/javadoc/2.12/com/fasterxml/jackson/annotation/JsonProperty.html#defaultValue--)
If I send a JSON like:
{
"myId": "AB123",
"name": "my attribute name"
}
I get the error described previously, and the default value of the data field is ignored.
If I send:
{
"myId": "AB123",
"name": "my attribute name",
"data": {}
}
I don't get an error, because I send also the data field.
Can you tell me where am I doing wrong, please?
Thanks
Do you have a default constructor? By default jackson requires a default constructor. This is not very common with data classes so you can either provide the constructor or you can do something like this:
#Bean
fun objectMapper(): ObjectMapper = ObjectMapper()
.registerKotlinModule()

Jackson Object Mapper class given an error Spring mvc

Jackson Object Mapper class given an error Spring mvc
All required jar already added no error in project like jackson-core-asl, jackson-core-2.2.3 and jackson-all 1.9.0 still getting error
Remove the unnecessary jackson-all and jackson-core-asl dependencies.
Include the only one jackson-databind that automatically de/serializes the objects.
<jackson.version>2.8.9</jackson.version>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
Don't forget to return the whole List<Demo> instead of String.
#RequestMapping(value="/getJson", method = RequestMethod.GET)
public List<Demo> listJsonList {
// ...
return alldatalist;
}
And please, next time copy-paste the source code as a text, not as the image :)

SpringMvc controller to returns JSON, displays error: HTTP status 406

I am learning spring 4.2.4 by writing some webapp code.The idea is to return json file by controller.
I have already posted my questions before couple of days ago and still no i could get the right suggestions for my case. I am trying all the suggestions given by stackoverfolow none of the suggestions could work for me. Here is my controller:
.....
#RequestMapping(value="/getmessages",method=RequestMethod.GET, produces="application/json")
#ResponseBody
public Map<String,Object> getMessage(Principal prinicipal){
List<Message>message=null;
if(prinicipal==null){
message=new ArrayList<Message>();
}
else{
String username=prinicipal.getName();
message=usersService.getMessage(username);
}
Map<String,Object> data= new HashMap<String,Object>();
data.put("message", message);
data.put("number", message.size());
System.out.println("message has to be her\n"+message);
System.out.println("Number message has to be her is..."+message.size());
return data;
}
the message content which is to be retrieved from mysql is propely displayed in console.
The problem is conversion to JSON and return the result. I have been trying by change the jackson 1.9.x jar to jackson-fasterxml-2.x and it does not work. All other possible configuration of servlete also does not work for me.
When I add jackson-fasterxml-databind ....it displays file download dialogue box for filename"getmessages". to download and save...
I am very grateful for your help.
Finally I have solved this problem as follow:
I changed my return type from MAP to String and I converted my MAP to String in side my CONTROLLER as:
Converting my Map to String:
ObjectMapper mapper = new ObjectMapper();
String jsonFromMap = mapper.writeValueAsString(data);
I have also changed my dependencies as:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.2.3</version>
Inside #RequestMapping change
produces=application/json
to
produces=text/html
I think the problem is with browser unable to understand application/json and returning Map............
Any how I did what I want to do even-though I do not know how I did it!

deserialization using jackson objectmapper fails when json has additional fields.How to solve?

Thanks in advance. I am using version 1.9.2
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.2</version>
</dependency>
org.codehaus.jackson.map.ObjectMapper jsonMapper = new org.codehaus.jackson.map.
jsonMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES , false);
JsonNode listNode = jsonMapper.readTree(json);
Iterator<JsonNode> it = listNode.getElements();
while (it.hasNext()) {
JsonNode moNode = it.next();
String className = moNode.get("objectClass").asText();
String moNodeText = moNode.toString();
Class<?> moClass = Class.forName(className);
Object ob = jsonMapper.readValue(moNodeText, moClass);
MyObject mo = (MyObject) ob;
moSet.add(mo);
}
But it keep failing pointing to additional fields in json.
(was java.lang.UnsupportedOperationException) (through reference chain: com.xxx.MyObject["additional_field_Json"])
I tried parser but got same error. any help?
thanks
Gopi
2 >>>> nodeText :{"objectclass":"com.xxx.xxx.MetaInfo$Flow",............,"fieldonlyexistinjson":["VALUE1","VALUE2","VALUE3"],"subFlows":[]}
2014-04-23 17:39:48,549 - ERROR main com.xxx.xxx.TestMetaDataCache.testImportMetadataFromJson (TestMetaDataCache.java:86) exception
org.codehaus.jackson.map.JsonMappingException: (was java.lang.UnsupportedOperationException) (through reference chain: com.xxx.xxx.Flow["objectTypes"])
at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:218)
at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:183)
at org.codehaus.jackson.map.deser.BeanDeserializer.wrapAndThrow(BeanDeserializer.java:1462)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:699)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:580)
at org.codehaus.jackson.map.ObjectMapper._readValue(ObjectMapper.java:2695)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1279)
at org.codehaus.jackson.JsonParser.readValueAs(JsonParser.java:1336)
at com.xxx.xxx.TestMetaDataCache.testImportMetadataFromJson(TestMetaDataCache.java:80)
No, that is not the same exception: "UnsupportedOperationException" is not what you get for unrecognized property. Can you include full stack trace for exception?
My guess is that you have an immutable List or Map somewhere, and deserializer is trying to add entries to it.

angularjs + spring mvc + json post request

I've been doing some research on the web regarding my problem, and I feel that my code reflects what's written in most of the examples - and yet, it still doesn't work. Thus my question.
Long story short, I want to send POST request to add new item to some "backend". For REST API I use Spring MVC, for sending the request I use $http from AngularJS
That's how I invoke the POST request
$scope.testAddItem = function(){
$http({
'url' : 'addNewItem',
'method' : 'POST',
'headers': {'Content-Type' : 'application/json'},
'data' : $scope.newItem
}).success(function(data){
$scope.marketForm.texts.push({'text' : data.text});
})
}
Which maps to the proper URL. Problem is that I get the following response
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<title>Error 400 BAD_REQUEST</title>
</head>
<body><h2>HTTP ERROR 400</h2>
<p>Problem accessing /poll/addNewItem/. Reason:
<pre> BAD_REQUEST</pre></p><hr /><i><small>Powered by Jetty://</small></i><br/>
I get this error either when I click the button on the website, and when I'm testing it via some REST Client.
Dependencies I've included in my pom.xml
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
One note - sending other request via GET works.
My Controller class
#Controller
#RequestMapping(value = "/")
public class PollController {
#RequestMapping(method = RequestMethod.GET)
public String mainPage(){
return "poll";
}
#RequestMapping(value = "/getNewElement")
public #ResponseBody
List<PollItem> getNewElement(){
List<PollItem> listOfItems = new ArrayList<PollItem>(2);
listOfItems.add(new PollItem("test 1"));
listOfItems.add(new PollItem("test 2"));
return listOfItems;
}
#RequestMapping(value = "/addNewItem", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody PollItem addNewElement(#RequestBody PollItem pollItem){
pollItem.setId(2); // I know it makes no logical sense, but it's just for testing.
return pollItem;
}
}
Any clues ?
EDIT
After adding debug mode it seems that it's some JSON parsing problem
Method [public com.poll.model.PollItem com.poll.controller.PollController.addNewElement(com.poll.model.PollItem)]
org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unexpected character ('a' (code 97)): expected a valid value (number, String, arr
ay, object, 'true', 'false' or 'null')
at [Source: HttpInputOverHTTP#5ce15706; line: 1, column: 2]; nested exception is org.codehaus.jackson.JsonParseException: Unexpected character ('a' (code 97)): expected
a valid value (number, String, array, object, 'true', 'false' or 'null')
at [Source: HttpInputOverHTTP#5ce15706; line: 1, column: 2]
at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.readJavaType(MappingJacksonHttpMessageConverter.java:187)
at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.read(MappingJacksonHttpMessageConverter.java:179)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodAr
gumentResolver.java:138)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:183)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:98)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:79)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:157)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:124)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:738)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:551)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:568)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:221)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1111)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:478)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:183)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1045)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:199)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:109)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:462)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:279)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:232)
at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:534)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:607)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:536)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.codehaus.jackson.JsonParseException: Unexpected character ('a' (code 97)): expected a valid value (number, String, array, object, 'true', 'false' or 'null'
)
at [Source: HttpInputOverHTTP#5ce15706; line: 1, column: 2]
at org.codehaus.jackson.JsonParser._constructError(JsonParser.java:1433)
at org.codehaus.jackson.impl.JsonParserMinimalBase._reportError(JsonParserMinimalBase.java:521)
at org.codehaus.jackson.impl.JsonParserMinimalBase._reportUnexpectedChar(JsonParserMinimalBase.java:442)
at org.codehaus.jackson.impl.Utf8StreamParser._handleUnexpectedValue(Utf8StreamParser.java:2090)
at org.codehaus.jackson.impl.Utf8StreamParser._nextTokenNotInObject(Utf8StreamParser.java:606)
at org.codehaus.jackson.impl.Utf8StreamParser.nextToken(Utf8StreamParser.java:492)
at org.codehaus.jackson.map.ObjectMapper._initForReading(ObjectMapper.java:2770)
at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2718)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1923)
at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.readJavaType(MappingJacksonHttpMessageConverter.java:184)
... 38 more
EDIT2
It seems that it works, problem is that it supports only " (double quotes) where I want to use single-quotes. Is there any reason why I should double quotes always when doing JSON?
And what I should do change default behaviour of JSON mapper?
Ok, to answer the question - issue was that I used badly formatted JSON. I should be using double-quotes instead of single quotes (which is basically follwoing JSON standard. I'm new to this and I was a little bit confused, because a lot of websites uses single quotes for their examples - like for instance google charts ).
{"id":10,"text":"smth smth"}
is good
{'id':10,'text':'smth smth'}
is bad:)
That's true if your JSON is not mapped correctly with server side object then it will throw exception. I found very nice simple example here working exactly what you are looking for:
AngularJS Post Spring MVC JSON Example
AngularJS Form Post Spring MVC JSON
You may be missing the default constructor in your PollItem domain.
public class PollItem {
public PollItem () {
}
//your rest of the codes
}
Add this and your code will work just fine.
You already have a constructor defined in PollItem, which is making it the default constructor. Therfore adding the dummy constructor will solve your problem