JAXB Map String to Enum Values in Generated XSD - enums

I have a simple POJO with a String property. This String property actually contains values backed by a Java Enum. For reasons that I won't go into here, I can't just use the enum type on my POJO. Is there any JAXB annotation I can use on the String property such that when the XSD is generated, I have the values restricted to the the backing list of Enum values?

You should be able to use an XmlAdapter for this use case:
public class MyEnumAdapter extends XmlAdapter<MyEnum, String> {
...
}
Then on your class register the XmlAdapter on the String property that corresponds to the enum.
#XmlJavaTypeAdapter(MyEnumAdapter.class)
public String getValue() {
return value;
}

Related

Can't get Nest.PropertyName to be considered for nested

I have a type of entry in elastic that is made of some imbricated properties like
{
"_source":
{
"pipeline_version":1.7,
"agent":{
"hostname":"SFPWEW11616",
"id":"a1df2f4e-6dde-43fd-8af6-b3726124fdf7",
"type":"winlogbeat",
"ephemeral_id":"78be9770-dab9-4c56-a67e-b1a372a2f899",
"version":"7.5.1"
}
}, [...]
}
I'm trying to get my POCO to represent a flatten vie of this object. According to what I found in the documentation, I tried doing something in the like of
Friend Class ElasticEventLogEntry
<Nest.PropertyName("agent.hostname")>
Public Property AgentHostName As String
[...]
End Class
But no matter what I try, the value is always empty. I've seen some other posts using the NestedAttribute attribute but from what I could find, this is only useful if we want to also create nested objects in our POCO structure which isn't my case. What am I missing?
It's not possible to do what you're trying to do, at least not without writing your own JSON serialization for your ElasticEventLogEntry type and hooking up with JsonNetSerializer.
A better approach would be to model ElasticEventLogEntry differently
Public Class ElasticEventLogEntry
<DataMember(Name:="pipeline_version")>
Public Property PipelineVersion As String
Public Property Agent As Agent
End Class
Public Class Agent
Public Property Hostname As String
Public Property Id As String
Public Property Type As String
<DataMember(Name:="ephemeral_id")>
Public Property EphemeralId As String
Public Property Version As String
End Class
Then agent hostname will be deserialized to .Agent.Hostname

Overriding standard ID scalar

I want to use UUID as an identifier but standard scalar ID is coerced as string.
So have to parse uuid from string everywhere I use ID type.
I wonder is it possible to override ID type with my own implementation?
This scalar type has some special meaning or I can just use my own scalar called UUID as identifier?
We can not override the available scalers, please refer this link for discussion.
You can define a UUIDScalar in your code, for the same you will have to override the following methods
#Override
public Object serialize(Object dataFetcherResult) {
//
}
#Override
public Object parseValue(Object input) {
//
}
#Override
public Object parseLiteral(Object input) {
//
}
Reference: Making custom scalars in graphql java
Luckily the code for making custom scalar for UUID is available online, you can use this PR

Spring MVC mapping #RequestBody with variables containing a dot

I am doing a POST request to my Rest Contoller with the following object:
{
"relationship.name": "someting"
}
I'd like to map that to a POJO:
public class Request {
private String relationshipName;
// Getters, setter and contructor
}
How would I dot that?
Annotate your property with #JsonProperty
public class Request {
#JsonProperty("relationship.name")
private String relationshipName;
...
}
By default, the mapping will use the variable name as the key for the property. So without the annotation, it would expect relationshipName. #JsonProperty allows you to customize the key without changing the variable name.
Have u tried using #JsonProperty on relationshipName?
#JsonProperty(name), tells Jackson ObjectMapper to map the JSON property name to the annotated Java field's name.

Spring: #NestedConfigurationProperty List in #ConfigurationProperties

Hi I am trying to get the following configuration up and running.
#ConfigurationProperties(prefix="my")
public class Config {
#NestedConfigurationProperty
private List<ServerConfiguration> servers = new ArrayList<ServerConfiguration>();
public List<ServerConfiguration> getServers() {
return this.servers;
}
}
#ConfigurationProperties(prefix = "server")
public class ServerConfiguration {
private String name;
private String description;
}
So, I want to have multiple server configs nested in objects.
I tried setting the properties with the following properties file. I can see that the list is added up by items but the members of the server are never set (name, description)
my.servers[0].name=test
my.servers[0].server.name=test
my.servers[1].name=test
my.servers[1].server.name=test
To extend what Maciej said already.
#ConfigurationProperties should be set only on root objects (that is objects that are responsible to handle a given prefix. There is no need to annotated nested objects with it.
#NestedConfigurationProperty is only used by the meta-data generator (to indicate that a property is not a single value but something we should explore to generate additional meta-data. In the case of the List there isn't any finite amount of properties so the meta-data will have to stop at the list.
In any case you need a getter and a setter for each singular property. We don't do field binding and we require a public getter to avoid exposing unnecessary properties in the meta-data.
You need to add setters and getters to ServerConfiguration
You don't need to annotate class with nested properties with #ConfigurationProperties
There is a mismatch in names between ServerConfiguration.description and property my.servers[X].server.name=test

How do you handle deserializing empty string into an Enum?

I am trying to submit a form from Ext JS 4 to a Spring 3 Controller using JSON. I am using Jackson 1.9.8 for the serialization/deserialization using Spring's built-in Jackson JSON support.
I have a status field that is initially null in the Domain object for a new record. When the form is submitted it generates the following json (scaled down to a few fields)
{"id":0,"name":"someName","status":""}
After submitted the following is seen in the server log
"nested exception is org.codehaus.jackson.map.JsonMappingException: Can not construct instance of com.blah.domain.StatusEnum from String value '': value not one of the declared Enum instance names"
So it appears that Jackson is expecting a valid Enum value or no value at all including an empty string. How do I fix this whether it is in Ext JS, Jackson or Spring?
I tried to create my own ObjectMapper such as
public class MyObjectMapper extends Object Mapper {
public MyObjectMapper() {
configure(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
}
}
and send this as a property to MappingJacksonMappingView but this didn't work. I also tried sending it in to MappingJacksonHttpMessageConverter but that didn't work. Side question: Which one should I be sending in my own ObjectMapper?
Suggestions?
The other thing you could do is create a specialized deserializer (extends org.codehaus.jackson.map.JsonDeserializer) for your particular enum, that has default values for things that don't match. What I've done is to create an abstract deserializer for enums that takes the class it deserializes, and it speeds this process along when I run into the issue.
public abstract class EnumDeserializer<T extends Enum<T>> extends JsonDeserializer<T> {
private Class<T> enumClass;
public EnumDeserializer(final Class<T> iEnumClass) {
super();
enumClass = iEnumClass;
}
#Override
public T deserialize(final JsonParser jp,
final DeserializationContext ctxt) throws IOException, JsonProcessingException {
final String value = jp.getText();
for (final T enumValue : enumClass.getEnumConstants()) {
if (enumValue.name().equals(value)) {
return enumValue;
}
}
return null;
}
}
That's the generic class, basically just takes an enum class, iterates over the values of the enum and checks the next token to match any name. If they do it returns it otherwise return null;
Then If you have an enum MyEnum you'd make a subclass of EnumDeserializer like this:
public class MyEnumDeserializer extends EnumDeserializer<MyEnum> {
public MyEnumDeserializer() {
super(MyEnum.class);
}
}
Then wherever you declare MyEnum:
#JsonDeserialize(using = MyEnumDeserializer.class)
public enum MyEnum {
...
}
I'm not familiar with Spring, but just in case, it may be easier to handle that on the client side:
Ext.define('My.form.Field', {
extend: 'Ext.form.field.Text',
getSubmitValue: function() {
var me = this,
value;
value = me.getRawValue();
if ( value === '' ) {
return ...;
}
}
});
You can also disallow submitting empty fields by setting their allowBlank property to false.
Ended up adding defaults in the EXT JS Model so there is always a value. Was hoping that I didn't have to this but it's not that big of a deal.
I have the same issue. I am reading a JSON stream with some empty strings. I am not in control of the JSON stream, because it is from a foreign service. And I am always getting the same error message. I tried this here:
mapper.getDeserializationConfig().with(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
But without any effect. Looks like a Bug.

Resources