Dynamodb - Convert enumerator collection - java

Is there a way to convert a collection of enums? I've tried the following without success:
#DynamoDBTypeConvertedEnum
#DynamoDBAttribute(attributeName="myEnums")
private Collection<MyEnum> myEnums;

In order to save it as collection (i.e. set of strings), please use #DynamoDBTyped annotation with SS attribute type.
#DynamoDBTyped(DynamoDBAttributeType.SS)
#DynamoDBAttribute(attributeName = "myEnums")
public Set<MyEnum> getMyEnums() {
return myEnums;
}

myEnums is a Set of enums, not an enum itself.
DynamoDBTyped
The enum type is only supported by override or custom converter
Because you have a set of enums, you will need to use a customer converter. So remove the #DynamoDBTypeConvertedEnum annotation and use a custom converter. You can see an example I have posted before here. Its a generic Set example but it will work for your enum Set.
EDIT: i.e. use DynamoDBTypeConverted

Related

Can I ignore a getter-based write-only property during deserialization in Java Jackson?

I have a legacy JSON API class that I'm evolving to remove a certain property. It's currently at a point where the property value is always the same constant, so I would like my Java code to be just a simple getter with no underlying field for it. I want to continue serializing the value until I know that all my clients have migrated off of using the value. The object is only read by my clients, so I don't have to worry about them sending other values across.
public class MyType {
private String value;
public boolean isLegacyValue() {
return true;
}
}
That said, I don't want any test code or the like to fail if I deserialize a full value with the now-constant property. Is there a way I can tell Jackson to serialize a setter method-only property, but ignore it on deserialization? I tried a few different things, but I get a UnrecognizedPropertyException on deserialization. I'd rather not change the global DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES just for this one property.
{"value": "ABC", "legacyValue": true}
Also acceptable would be a way to tell Jackson to include the value without including a Java field for it.
I'm aware I can add a getter in addition to my setter, or make it a field, but both those options feel like they're confusing the Java API, as it's not actually matching the constant constraint:
public void setLegacyValue(boolean legacyValue) {
// No-op; only exists for Jackson deserialization
}
One thing I've found to work through trial and error is making it a final field. For whatever reason, Jackson knows to handle that as a write-only constant in a way that doesn't work with the getter without matching setter. This will be my solution if there's no way to do it with just a getter.
private final boolean legacyValue = true;
public boolean isLegacyValue() {
return legacyValue;
}
Jackson supports "one-way" properties using the access parameter of #JsonProperty. Annotate your property like this:
#JsonProperty(access = READ_ONLY)
public boolean isLegacyValue() {
return true;
}

Change naming of attributes in json without #JsonProperty

I have to convert my json from camelCase to kebab-case.
Example:
My Json:
{
"disclaimerConfirmed" : true
}
And I need:
{
"disclaimer-confirmed" : true
}
I cannot use #JsonProperty because it rename this atributes permanently. I am looking for something which will consume Json (can be as String) and returns modified json(as String).
Jackson supports naming strategies so you could read the input String to map (with camelCase strategy) and then write the map back to a String (with kebab-case which is natively supported );
Specific method you need to switch these conventions in ObjectMapper without annotations is:
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.*);
You can have different serializers for different cases or you can create pojo with #JsonProperty and use those where-ever required.
For example,
class A {
private String disclaimerConfirmed;
}
class AkebabCase {
#JsonProperty("disclaimer-confirmed")
private String disclaimerConfirmed;
}
So, if you want to serialize to kebab-case you can use converters to convert A to AkebabCase and then serialize.

Using swagger to document a string from enum values

I am getting the following error when trying to get the enum values for an allowableValues tag.
The value for annotation attribute ApiModelProperty.allowableValues
must be a constant expression
What I am trying to do:
#ApiModelProperty(allowableValues = new Enums().enumToString(SomeEnum.class))
private String someString;
Here is the logic for Enums().enumToString
public class Enums {
public final <E extends Enum<E>> String enumToString(Class<E> inputEnum) {
//inputEnum;
for (Enum enumValues : EnumSet.allOf(inputEnum)) {
//will create a string of the enum values
}
return "will be a formatted string of the enum values";
}
}
Is it possible to do what I am trying to accomplish? I know it is possible to just expose the enum in my API and swagger would then recognize the allowed values automatically, however the field in question needs to be exposed as a string, even though our internal logic has it as an enum.
Thanks in advance for your help!
#ApiModelProperty(value = "embed", dataType = "[Lmodel.request.Embed;")
private final List<String> embed;
the Embed path is a list of enums. This show you something like this in the swagger documentation:
type: "object"
properties:
embed:
type: "array"
description: "embed"
items:
type: "string"
enum:
-SOME
-SOME
-SOME
-SOME
Your problem is not related to Swagger at all but basic Java.
In Java annotations, you can have constant expressions, meaning you can't do method calls there, any other things but only use constant values.

How to tell Jackson to ignore a field during serialization if its value is null?

How can Jackson be configured to ignore a field value during serialization if that field's value is null.
For example:
public class SomeClass {
// what jackson annotation causes jackson to skip over this value if it is null but will
// serialize it otherwise
private String someValue;
}
To suppress serializing properties with null values using Jackson >2.0, you can configure the ObjectMapper directly, or make use of the #JsonInclude annotation:
mapper.setSerializationInclusion(Include.NON_NULL);
or:
#JsonInclude(Include.NON_NULL)
class Foo
{
String bar;
}
Alternatively, you could use #JsonInclude in a getter so that the attribute would be shown if the value is not null.
A more complete example is available in my answer to How to prevent null values inside a Map and null fields inside a bean from getting serialized through Jackson.
Just to expand on the other answers - if you need to control the omission of null values on a per-field basis, annotate the field in question (or alternatively annotate the field's 'getter').
example - here only fieldOne will be omitted from the JSON if it is null. fieldTwo will always be included in the JSON regardless of if it is null.
public class Foo {
#JsonInclude(JsonInclude.Include.NON_NULL)
private String fieldOne;
private String fieldTwo;
}
To omit all null values in the class as a default, annotate the class. Per-field/getter annotations can still be used to override this default if necessary.
example - here fieldOne and fieldTwo will be omitted from the JSON if they are null, respectively, because this is the default set by the class annotation. fieldThree however will override the default and will always be included, because of the annotation on the field.
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Foo {
private String fieldOne;
private String fieldTwo;
#JsonInclude(JsonInclude.Include.ALWAYS)
private String fieldThree;
}
UPDATE
The above is for Jackson 2. For earlier versions of Jackson you need to use:
#JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
instead of
#JsonInclude(JsonInclude.Include.NON_NULL)
If this update is useful, please upvote ZiglioUK's answer below, it pointed out the newer Jackson 2 annotation long before I updated my answer to use it!
With Jackson > 1.9.11 and < 2.x use #JsonSerialize annotation to do that:
#JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
In Jackson 2.x, use:
#JsonInclude(JsonInclude.Include.NON_NULL)
You can use the following mapper configuration:
mapper.getSerializationConfig().setSerializationInclusion(Inclusion.NON_NULL);
Since 2.5 you can user:
mapper.setSerializationInclusion(Include.NON_NULL);
You can set application.properties:
spring.jackson.default-property-inclusion=non_null
or application.yaml:
spring:
jackson:
default-property-inclusion: non_null
http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
in my case
#JsonInclude(Include.NON_EMPTY)
made it work.
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonInclude(JsonInclude.Include.NON_EMPTY)
should work.
Include.NON_EMPTY indicates that property is serialized if its value is not null and not empty.
Include.NON_NULL indicates that property is serialized if its value is not null.
This Will work in Spring boot 2.0.3+ and Jackson 2.0+
import com.fasterxml.jackson.annotation.JsonInclude;
#JsonInclude(JsonInclude.Include.NON_NULL)
public class ApiDTO
{
// your class variable and
// methods
}
If you want to add this rule to all models in Jackson 2.6+ use:
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
If in Spring Boot, you can customize the jackson ObjectMapper directly through property files.
Example application.yml:
spring:
jackson:
default-property-inclusion: non_null # only include props if non-null
Possible values are:
always|non_null|non_absent|non_default|non_empty
More: https://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html#howto-customize-the-jackson-objectmapper
For Jackson 2.5 use :
#JsonInclude(content=Include.NON_NULL)
If you're trying to serialize a list of object and one of them is null you'll end up including the null item in the JSON even with
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
will result in:
[{myObject},null]
to get this:
[{myObject}]
one can do something like:
mapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
#Override
public void serialize(Object obj, JsonGenerator jsonGen, SerializerProvider unused)
throws IOException
{
//IGNORES NULL VALUES!
}
});
TIP: If you're using DropWizard you can retrieve the ObjectMapper being used by Jersey using environment.getObjectMapper()
This has been troubling me for quite some time and I finally found the issue. The issue was due to a wrong import. Earlier I had been using
com.fasterxml.jackson.databind.annotation.JsonSerialize
Which had been deprecated. Just replace the import by
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;
and use it as
#JsonSerialize(include=Inclusion.NON_NULL)
Global configuration if you use Spring
#Configuration
public class JsonConfigurations {
#Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.serializationInclusion(JsonInclude.Include.NON_NULL);
builder.serializationInclusion(JsonInclude.Include.NON_EMPTY);
builder.failOnUnknownProperties(false);
return builder;
}
}
We have lot of answers to this question. This answer may be helpful in some scenarios
If you want to ignore the null values you can use the NOT_NULL in class level.
as below
#JsonInclude(Include.NON_NULL)
class Foo
{
String bar;
}
Some times you may need to ignore the empty values such as you may have initialized the arrayList but there is no elements in that list.In that time using NOT_EMPTY annotation to ignore those empty value fields
#JsonInclude(Include.NON_EMPTY)
class Foo
{
String bar;
}
Case one
#JsonInclude(JsonInclude.Include.NON_NULL)
private String someString;
Case two
#JsonInclude(JsonInclude.Include.NON_EMPTY)
private String someString;
If someString is null, it will be ignored on both of cases.
If someString is "" it just only be ignored on case two.
The same for List = null or List.size() = 0
Try this -
#JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
public class XYZ {
protected String field1;
protected String field2;
}
And for non-null values (On getters/class level) -
#JsonSerialize(include=JsonSerialize.Inclusion.NON_EMPTY)
Jackson 2.x+ use
mapper.getSerializationConfig().withSerializationInclusion(JsonInclude.Include.NON_NULL);
Also, you have to change your approach when using Map myVariable as described in the documentation to eleminate nulls:
From documentation:
com.fasterxml.jackson.annotation.JsonInclude
#JacksonAnnotation
#Target(value={ANNOTATION_TYPE, FIELD, METHOD, PARAMETER, TYPE})
#Retention(value=RUNTIME)
Annotation used to indicate when value of the annotated property (when used for a field, method or constructor parameter), or all properties of the annotated class, is to be serialized. Without annotation property values are always included, but by using this annotation one can specify simple exclusion rules to reduce amount of properties to write out.
*Note that the main inclusion criteria (one annotated with value) is checked on Java object level, for the annotated type, and NOT on JSON output -- so even with Include.NON_NULL it is possible that JSON null values are output, if object reference in question is not `null`. An example is java.util.concurrent.atomic.AtomicReference instance constructed to reference null value: such a value would be serialized as JSON null, and not filtered out.
To base inclusion on value of contained value(s), you will typically also need to specify content() annotation; for example, specifying only value as Include.NON_EMPTY for a {link java.util.Map} would exclude Maps with no values, but would include Maps with `null` values. To exclude Map with only `null` value, you would use both annotations like so:
public class Bean {
#JsonInclude(value=Include.NON_EMPTY, content=Include.NON_NULL)
public Map<String,String> entries;
}
Similarly you could Maps that only contain "empty" elements, or "non-default" values (see Include.NON_EMPTY and Include.NON_DEFAULT for more details).
In addition to `Map`s, `content` concept is also supported for referential types (like java.util.concurrent.atomic.AtomicReference). Note that `content` is NOT currently (as of Jackson 2.9) supported for arrays or java.util.Collections, but supported may be added in future versions.
Since:
2.0

Binding a JSON to a Java class using JAXB

I have the following JSON, where can be either true or false:
{"flag1":<boolean value>, "flag2":<boolean value>}
And I have tried to bind it to a Java class using Jersey and the following JAXB annotations:
#XmlRootElement
public class MyClass {
#XmlElement(name = "flag1", type = Boolean.class)
private Boolean flag1;
#XmlElement(name = "flag2", type = Boolean.class)
private Boolean flag2;
...
}
The problem is that when I assign a non-boolean value to 'flag1' or 'flag2', like in the example below, JAXB automatically assigns a false value to the 'flag1' and 'flag2' fields of MyClass.
{"flag1":"foo", "flag2":"bar"}
Is there a way to annotate 'MyClass' so that when JSON's 'flag1' and 'flag2' are not boolean I get an exception?
It looks like Jersey is simply using Boolean.valueOf, which treats everything other than a literal "true" as false. Since JavaScript doesn't have a notion of variable type, this is an arguably valid behavior.
An XML mapping, by comparison, is based on a schema definition, which does have a very specific notion of boolean values.
Not having used Jersey (or JAXB since the 1.x days), I'm wondering if you have to annotate the actual variables, or if you could annotate the setters. Or perhaps you could provide a setter that takes a String and parses it, instead of / along with a setter that takes a boolean.
What you showed would work the way you want (throw an exception) if you used pure Jackson JAX-RS provider. It does accept some variations (1 and 0, since some languages do not have native boolean type), but not things that have no meaningful equivalent.
Alternatively, as suggested, a setter method with type String would make sense, since then you could manually control conversions.

Categories

Resources