Is there a Java formatting library for user input? - java

This seems like it would be a really common thing to need in just about any Java project. And yet I am unable to find anything that serves this purpose.
I used to use a web framework called Stripes Framework, that had annotation driven validators and automatic formatting via their validator API.
Example:
#Validate(maxlength = ModelConstants.NAME_MAX_LENGTH, converter = CapitializeFullyTypeConverter.class)
private String name;
#Validate(maxlength = ModelConstants.NAME_MAX_LENGTH, converter = EmailTypeConverter.class)
private String email;
Those fields would be defined on your controller action bean, and all user input would automatically be validated and formatted according to the specified rules.
If someone would enter their email address as: "TEST#TEST.COM"
Then it would automatically be formatted to: "test#test.com"
I would like to find something like this for automatically formatting data within DTOs.
If nothing like this is available, what is the usual way of handling this? Surely everyone is not writing custom formatting functions for each getter within the DTO?

Assumption: meaning of "formatter" as type-converter
When you ask for annotation based "formatter" you mean Stripe Framework's #Validate annotation with its parameter converter. The converter can be parameterized as:
(class) The converter class that will be used to transform this parameter into its object representation
In the Web-MVC context this means the converter is used to convert the request-parameter, exactly its source value, as supplied by the incomming web-request. The converted value is then stored as target value to the (DTO) object's property.
Example: Conversion of (DTO) Strings
Web request is given incommong with parameter name email and value string TEST#EXAMPLE.COM. This should the be converted to lowercase and strored in the DTO's property (a.k.a attribute or field ) email as value test#example.com.
Spring annotations for DTOs
Spring Framework also uses the concepts of request validation and request conversion. It also allows to configure these annotations-driven on the DTOs or classes and their attributes.
The validation leverages Java Bean Validation standard (JSR-303) javax.validation annotations like #Valid and #Length.
The conversion is part of the HttpConverters used for serialization/deserialization of responses/requests to/from objects (DTO). Therefore Spring allows to inlude object-relational mapper (ORM) frameworks or libraries as (e.g. Maven) dependencies. These bring their own annotations regarding conversation with them.
Fasterxml's Jackson
Jackson (ORM) for example uses the annotation #JsonFormat to achieve simple string conversions - but only for non-string fields like Date or Number (as far as I know).
It also allows complete customisation of serializers and deserializers via annotations #JsonSerialize and #JsonDeserialize.
Note, that although many annotations in Jackson are named with "Json" they mostly also apply to XML or even other data formats (representations) like CSV, etc.
String To Lowercase with Jackson
Your question was asked for Jackson: How to force Jackson deserialize field values to lower case and answered.
See also
Difference between #Valid and #Validated in Spring
Use Jackson to deserialize JSON string or object into a String field
DZone: Tutorial on Jackson Deserialization Annotations
Bealdung (2019): Getting Started with Custom Deserialization in Jackson

If you are using Spring Mvc, you have access to a formatting API.
There are pre-existing annotations in the org.springframework.format.annotation package for date and number formatting.
If you need custom formatting rules, you can write your own and register it via the FormattingConversionServiceFactoryBean.
See some examples here: https://docs.spring.io/spring-framework/docs/3.2.0.RC1/reference/html/validation.html

Related

Forced global validation of String values in JSON body of Spring MVC controllers without annotations

I would like to ask if there exists a sane way to validate all string fields/values in a JSON #RequestBody of the MVC controller:
all fields of String type are validated by default, unless overridden by special annotation
the validation should check allowed characters and length
Solutions that I know of, but do not seem ideal for the use-case:
javax.validation via annotations -- one must not forget to add the annotation, the validation should be performed on every string unless said otherwise
org.springframework.validation.Validator most likely possible, but quite a lot of custom reflection code
some kind of component scan in unit test that checks that classes with certain suffix in name (*DTO?) does have all String fields annotation with validation annotation
use javax.validation + code-review
We all know that we can use xsd to validate xml instance. If you want to go ahead with JSON as well. Maybe you need checkout json schema.
As for java validator. You can refer to here
Hope it can help.

Field name serialization in MongoDB + Spring data

I am wondering about the possibility of field name serialization in MongoDB using Spring data. What I meant in field name serialization is, let's say I have a field called 'projectName' and I want to store this field name as it is in MongoDB but when it is converted to JSON, I want it to be 'project_name'.
I know that I can do this through MongoConverter, but I am wondering is there an annotation like Gson's #SerializedName so I do not have to do conversions for entire classes just because of field names.
As I mentioned earlier, I am using Spring data to work with MongoDB.
Please note that I am aware about #Field annotation which converts the POJO field name into a custom MongoDB field name which I do not need in this case.
Thanks in advance!

Using polymorphism at deserialization time with Jackson (and MrBean)

I'm using Jackson to deserialize some JSON into Java POJOs. I register the MrBean module with my object mapper, so all I have to do is define a bunch of interfaces, and the POJOs are generated automagically, based on those interfaces.
I would like to have a Credentials interface with various types of credentials that extend it, e.g. UsernamePasswordCredentials and CertificateFileCredentials.
Doing this without any annotations or other incantations to try to make it work gives me the following error in my unit test:
org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "username" (Class org.codehaus.jackson.generated.SCRUBBED.Credentials), not marked as ignorable
at [Source: java.io.StringReader#e0b6f5; line: 32, column: 29] (through reference chain: HostConfiguration["hostDefinitions"]->HostDefinition["credentials"]->Credentials["username"])
I've also followed the instructions at another StackOverflow post, and I'm getting the same error.
The error makes sense; Jackson is trying to map the contents of my JSON file to an empty interface. However, I (naively, perhaps) expected Jackson to look for interfaces that extend the base Credentials interface and try to match up the fields in those interfaces to the fields it found in the JSON object.
I've seen some examples at the Jackson wiki that make use of meta-information in the JSON object, e.g. decorating an object with "#class":"foo.bar.CertificateFileCredentials", but I'd prefer to avoid any of that since my JSON input will be generated automatically by other services, and those other services shouldn't have to know anything about the internals of my service.
Thanks!
How would you define actual implementation classes? As additional interfaces? Those should get generated correctly; but the problem is during deserialization: there must be some way for deserializer to find out actual type to use, if there are multiple choices.
For this, #JsonTypeInfo is recommended to be used as you have noticed.
Actually, the technique would work well for your purposes too, even though you don't control the service that generates the JSON.
Saving the class name is a nice easy default when using #JsonTypeInfo but Jackson lets you customize this to your liking.
For example, suppose the service generates JSON that looks like this:
{ meows: 400, furColor: "green", species: "cat" }
Then you can define these interfaces to convert it properly.
#JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY,property="species")
#JsonSubTypes({
#JsonSubTypes.Type(value=Feline.class, name="cat")
})
public interface Animal {
public String getFurColor();
}
#JsonTypeName("cat")
public interface Feline extends Animal {
#JsonProperty("meows") // just to have an example of a renamed property...
public long getMeowingVolumeInDecibels();
}
Then you should just automatically get the right java type at runtime when deserializing, as well as automatically generate the "species" property depending on the runtime type. Hope that helps!

Map JSON Response to POJO (with different names)

I know there are numerous posts out there for a similar problem, but mine seems to be a bit different. I am reading in a bunch of JSON and would like to build POJO from it, but I don't want to use the names of the JSON result. Is there a way to "map" the element names in JSON to the attributes in my POJOs (using gson or Jackson maybe)?
It's worth mentioning this application is being built for Android.
Thanks in advance!
If you're using Gson, you can append an attribute to your objects, like so:
#SerializedName("ServicesResult")
public String services;
Where "ServicesResult" is the actual name of the element in the JSON.
With Jackson, you have multiple options:
Use #JsonProperty("name") annotation to indicate name to use in JSON, add directly or use mix-in annotations (external)
Specify PropertyNamingStrategy to convert from "Java name" to "JSON name" (there is default java<->c-style converter bundled with 1.9)
Modify AnnotationIntrospector to change the name using some other mechanism than annotations
Jackson will also interpret the Basic package javax.xml.bind.annotation
If you use those annotations you can readily move between Json/XML

java json controller

I have an Java class, like Library, that contains many fields. I want do ajax call to server
and in controller's method I want to have partly initialized #RequestBody Library with only
fields, which are present in json object.
I read the http://blog.springsource.com/2010/01/25/ajax-simplifications-in-spring-3-0/, but I need not full object.
Please Help
You could use a org.codehaus.jettison.json.JSONObject (part of the Jettison project) and only include the fields that you need.
Or, you could just make a simplified version of Library that includes only the fields that you want (call it AjaxLibrary or something).
It would not be a problem to use full object, cause fields would not be initialized, if they are not present at entire json.
Also you can create own DTO class, e.g. SomeActionLibraryDTO. Extract required fields from Library, and use #JsonIgnoreProperties(ignoreUnknown = true) annotation for class to ignore the rest of json object (I suppose you are using the default json jackson marshaller, right?)

Categories

Resources