I am currently using the objectMapper of Jackson to serialise values in a JSON and put them in a POJO. I need to validate those values so I use validation annotation such as #Regex, #Max and others.
So what happens for now is that I call objectMapper method to read JSON
publicEnquiry = objectMapper.readValue(jsonNode, Enquiry.class);
Then I retrieve all the validation messages in a list and I return it to the user.
payload = publicEnquiry.getPayload();
Set<ConstraintViolation<Enquiry<payload>>> constraintViolations =
publicEnquiry.getConstraintViolations();
Everything works fine if I send a too big integer, a bad formatted string, or anything that will not create a problem for the serialisation, but if I send a date formatted in an unexpected format, or simply bad formatted like "2010-02" instead of "2010-02-03", then I get a JsonMappingException. It is of course expected because the mapper can't understand a bad-formatted date.
However, I need to manage those exception and to be able to add a validation message each time it happens, in a way that will seem transparent for the user. I need a message like "Validation failed: the expected format is yyyy-MM-dd". And I need to perform the normal validation on the other properties opf the POJO like in a normal case.
Unfortunately, Jackson doesn't offer a method in the objectMapper that would skip the exception-generator fields and give back a list of those troublesome fields, or anything like that. It simply fails if there is a problem.
Does someone would have a solution or at least a suggestion on how to proceed ?
Related
I've just started to learn about serialization/deserialization and I'm a bit confused about which type is used where and when... let me explain:
I have an object containing many fields some of which are full of "useless" info.
Now, when I log the contents of such object for debugging purposes I would like the output to be in a nice json format.
So in the toString() method of this object I do the following:
import com.fasterxml.jackson.databind.ObjectMapper;
...
...
#Override
public String toString() {
ObjectMapper objectMapper = new ObjectMapper();
String s = "";
try{
s = objectMapper.writeValueAsString(this);
} catch (Exception e) {
}
return s;
}
but this also logs all the useless fields.
So I've looked around and found the #JsonIgnore annotation from com.fasterxml.jackson.annotation.JsonIgnore which I can put on top of the useless fields so as not to log them.
But from what I've understood serialization is a process of transforming a java object into a bytestream so that it can be written to file, saved in session, sent across the internet. So my noob question is: is it possible that using the #JsonIgnore annotation on top of certain fields will result in those fields not being saved into session (I use an hazelcast map), or not being sent in the http responses I send, or not being written to a file If I ever decide to do that?
If the answer to the previous question is NO, then is that because those types of actions (saving in session, writing to file, sending as http response) use different types of serialization than objectMapper.writeValueAsString(this); so they don't conflict?
In your case, you're using Jackson's ObjectMapper to convert your object to a string representation (in JSON format). The #JsonIgnore annotation is part of Jackson's annotations and will prevent fields annotated with it from being included in the JSON representation of your object.
However, this only affects the string representation created by the ObjectMapper, not other forms of serialization/deserialization. If you want to persist the object in a specific way, you may need to use a different form of serialization (such as binary serialization) or create a custom representation that excludes the fields you don't want to save.
So to answer your questions:
No, using #JsonIgnore will not affect the object saved in a session or sent as an HTTP response.
Yes, that's correct. Different forms of serialization/deserialization may handle fields differently, even if they are part of the same object.
I have an application, which loads a data row from a SQL Server database and should transmit that content JSON-encoded to a webservice. I used ObjectMapper to do the JSON conversion. There is some infrastructure behind this project, namely I get the data from the db as a Hashmap<string,object> where the keys are the column-names from the db-table.
Is there a way to tell com.fasterxml.jackson.databind.ObjectMapper how to format double-values upon serialization, when you can not use annotations?
I did a simple
ObjectMapper o = new ObjectMapper();
String jsonStr = o.writeValueAsString(m); // m is my hashmap-instance
While in theory this works quite nicely, I have a problem with the serialization of doubles. In the db there is a column of type float (which corresponds to double in Java, java-float would be real in SQL Server) with the value 402.4818. If I let ObjectMapper serialize this, I get 402.48179999999996 in JSON.
How can I customize the double-formatting / precision in ObjectMapper? I have already used setDateFormat(new SimpleDateFormat("yyyy-MM-dd")) to get my dates right, is there any way to do something similar for double?
Most examples in the net serialize POJOs where you can use annotations to specify how specific properties should be serialized, but I have a HashMap here.
Please don't tell me that I have to go through the hassle of creating a POJO, fill it with the DB-Data and serialize it for every row I want to send via this API. (This is a db-row which has > 30 columns and the project is nearly done, besides this little double-formatting-problem.)
So what do I need to do to tell ObjectMapper to round to the 4. decimal point before serializing or give some custom DecimalFormat? Documentation on this is quite sparse.
I need to convert a certain JSON string to a Java object. I am using Jackson ObjectMapper for reading the JSON. The JSON String is something like this:-
"{"emailId":"gmail#rajnikant.com","accessToken":"accTok"}4".
When I am using objectMapper.readValue() for reading the JSON string to a specific destination class, it should throw an exception because of the JSON string being appended by 4. What should I do so that only valid JSON can be read and in other cases it will throw an exception?
To Jackson, GSON and others, a JSON string with some characters appended after the last } is valid JSON as long as what is contained between the {} is valid JSON.
As stated by a member of FasterXML (Jackson) team:
Yes. This is by design. If you want to catch such problems, you need to construct JsonParser, advance it manually. Existence of multiple root-level values is not considered a validity problem.
Reference: https://github.com/FasterXML/jackson-databind/issues/726
So if you need to enforce "clean" JSON you'll have to extend the default parser with your own functionality. However, IMO if it's OK to the default parser it should be OK to you too (unless we're dealing with some inter-language incompatibility scenario here).
I'm calling 3rd party API and receiving as a response next string:
"[{\"name\":\"name\",\"id\":1}]"
As I see it's not valid json because it has quotes around it. Is it possible somehow to map it to java object with jackson, gson libraries?
Or anyway I should write my custom converter/deserializer?
You don't need a custom converter or deserializer. You could write one of course, but I wouldn't encourage you to do so. Be explicit about what is happening here, especially when you are working in a team. It's the other side that is at fault here, they are not outputting valid JSON.
With Jackson, deserialize their output this way:
ObjectMapper mapper = new ObjectMapper();
String json = theirOutput.substring(1, theirOutput.length - 1);
Object myObject = mapper.readValue(json, MyObject.clas);
Put some documentation above why you do it this way so everybody understands what's happening here. In my opinion this is a much cleaner solution than writing a custom converter or deserializer.
I have a RESTful web service that provides JSON that I am consuming. I am using Spring 3.2 and Spring's MappingJacksonHttpMessageConverter. My JSON looks like this:
{
"Daives": {
"Daive": {},
"Daive": {},
"Daive": {},
"Daive": {}
}
}
Now everything I have read seems to indicate that this JSON should be refactored to an array of JSON Daives. However, this is valid JSON so I want to make sure that I am thinking correctly before going back to the service provider to ask for changes. In the format above, I would have to know ahead of time how many Daives there are going to be such that my DTO accounted for them. The handy dandy Jackson mapper isn't going work with this kind of JSON setup. If the JSON was altered to provide and Array of JSON Daives, I could use a List to dynamically map them using Spring/Jackson.
Am I correct? Thanks :)
According to this thread, the JSON spec itself does not forbid multiple fields with the same name (in your case, multiple fields named "Daive" in the object "Daives").
However, most parsers will either return an error or ignore any value but the last one. As you said, putting these values into an array seems much more sensible; and indeed, you'll be able to map this array to a List with Jackson.