#JsonIgnore and #JsonProperty on same attribute - java

I need to ignore certain attributes in my Json Object based on a custom Ignore annotation, which I need only for a certain object mapper. But, for other cases, I need the JsonProperty annotation on it. I am using JacksonAnnotationInstrospector to do this. But when I do so, neither of the annotations get acknowledged.
For instance, I want my output to be such:
Normal object mapper:{"element3":"C","element_1":"A","element_2":"B"}
Expected output using Object mapper with JacksonAnnotationInstrospector:{"element_1":"A"}
The output I am actually getting with JacksonAnnotationInstrospector:{"element2":"B","element_1":"A"}
Following is my code:
public class TestClass {
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setAnnotationIntrospector(new JsonIgnoreIntrospector());
MockObject mockObject = new MockObject("A", "B", "C");
String string = objectMapper.writeValueAsString(mockObject);
System.out.println(string);
}
public static class MockObject {
#JsonProperty("element_1")
String element1;
#CustomJsonIgnore
#JsonProperty("element_2")
String element2;
#CustomJsonIgnore
String element3;
public MockObject(String element1, String element2, String element3) {
this.element1 = element1;
this.element2 = element2;
this.element3 = element3;
}
public String getElement1() {
return element1;
}
public void setElement1(String element1) {
this.element1 = element1;
}
public String getElement2() {
return element2;
}
public void setElement2(String element2) {
this.element2 = element2;
}
public String getElement3() {
return element3;
}
public void setElement3(String element3) {
this.element3 = element3;
}
}
public static class JsonIgnoreIntrospector extends JacksonAnnotationIntrospector {
#Override
public boolean hasIgnoreMarker(final AnnotatedMember m) {
return m.hasAnnotation(CustomJsonIgnore.class) || m.hasAnnotation(JsonIgnore.class);
}
}
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.CONSTRUCTOR})
#JacksonAnnotation
public #interface CustomJsonIgnore {
}
}

You should use annotation on getters rather than on fields. and also add METHOD in annotation target.
working solution:
public class TestClass {
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setAnnotationIntrospector(new JsonIgnoreIntrospector());
MockObject mockObject = new MockObject("A", "B", "C");
String string = objectMapper.writeValueAsString(mockObject);
System.out.println(string);
}
public static class MockObject {
String element1;
String element2;
String element3;
public MockObject(String element1, String element2, String element3) {
this.element1 = element1;
this.element2 = element2;
this.element3 = element3;
}
#JsonProperty("element_1")
public String getElement1() {
return element1;
}
public void setElement1(String element1) {
this.element1 = element1;
}
#CustomJsonIgnore
#JsonProperty("element_2")
public String getElement2() {
return element2;
}
public void setElement2(String element2) {
this.element2 = element2;
}
#CustomJsonIgnore
public String getElement3() {
return element3;
}
public void setElement3(String element3) {
this.element3 = element3;
}
}
public static class JsonIgnoreIntrospector extends JacksonAnnotationIntrospector {
#Override
public boolean hasIgnoreMarker(final AnnotatedMember m) {
return m.hasAnnotation(CustomJsonIgnore.class) || m.hasAnnotation(JsonIgnore.class);
}
}
#Retention(RetentionPolicy.RUNTIME)
#Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE,
ElementType.CONSTRUCTOR })
#JacksonAnnotation
public #interface CustomJsonIgnore {
}
}

I am not totally sure if I understand you use case. Why do you need a name on a property that you are ignoring?
If the issue is related to deserialisation and the deserialisation fails because it cannot find the desired property with a specific name, you can configure the object mapper to ignore unknown properties. Example follows.
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

Related

JSON to Java Object deserializer POJO Eror: Could not resolve subtype

I have a problem related to:
De-serializing JSON to polymorphic object model using Spring and JsonTypeInfo annotation
com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id '[' as a subtype
The solutions provided there didn't work for me.
I have the following DTO:
public class QuestionaireAnswersDTO {
#JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = As.EXISTING_PROPERTY)
#JsonSubTypes({
#JsonSubTypes.Type(name = "single", value = SingleChoiceAnswerDTO.class),
#JsonSubTypes.Type(name = "multi", value = MultipleChoiceAnswerDTO.class)
})
public static abstract class QuestionaireAnswerDTO {
String answerId;
String name;
public String getAnswerId() {
return answerId;
}
public void setAnswerId(String answerId) {
this.answerId = answerId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
String questionnaireId;
List<QuestionaireAnswerDTO> answers;
public String getQuestionnaireId() {
return questionnaireId;
}
public void setQuestionnaireId(String questionnaireId) {
this.questionnaireId = questionnaireId;
}
public List<QuestionaireAnswerDTO> getAnswers() {
return answers;
}
public void setAnswers(List<QuestionaireAnswerDTO> answers) {
this.answers = answers;
}
with those subclasses:
public static class SingleChoiceAnswerDTO extends QuestionaireAnswerDTO {
#Nullable
String selectedOption;
public String getSelectedOption() {
return selectedOption;
}
public void setSelectedOption(String selectedOption) {
this.selectedOption = selectedOption;
}
}
public static class MultipleChoiceAnswerDTO extends QuestionaireAnswerDTO {
List<String> selectedOptions;
public List<String> getSelectedOptions() {
return selectedOptions;
}
public void setSelectedOptions(List<String> selectedOptions) {
this.selectedOptions = selectedOptions;
}
}
Now I wanted to write a test using this json object:
{
"questionnaireId":"questionnaire1",
"answers":[
{
"name":"single",
"answerId":"Question1",
"selectedOption":"Yes"
},
{
"name":"multi",
"answerId":"Question3",
"selectedOptions":[
"yes",
"no"
]
}
]
}
Using this test:
JsonFactory factory = new JsonFactory();
factory.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
ObjectMapper mapper = new ObjectMapper(factory);
mapper.registerSubtypes(QuestionaireAnswersDTO.SingleChoiceAnswerDTO.class, QuestionaireAnswersDTO.MultipleChoiceAnswerDTO.class);
QuestionaireAnswersDTO result = mapper.readValue(testData, QuestionaireAnswersDTO.class);
String resultAsString = mapper.writeValueAsString(result);
System.out.println(resultAsString);
Which results in the following Error:
com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve subtype of [simple type, (...)
missing type id property '#class' (for POJO property 'answers')
Using the .registerSubtypes() method instead of JsonSubtypes didn't work here instead of JsonSubtypes. Same error occurs.

How to use #JsonSubTypes for polymorphic type handling with Jackson YAML Mapper

I discovered the #JsonTypeInfo annotation via https://www.baeldung.com/jackson-annotations and tried to use this in order to dynamically parse a given YAML-file into different POJOs. The YAML could look like this:
AWSTemplateFormatVersion: '2010-09-09'
Resources:
AWSSNSTopic:
Properties:
Subscription:
Endpoint: someEnpointInfo
Protocol: email
ResourceName: HelloWorldTopic
Type: AWS::SNS::Topic
AWSServerlessFunction:
Properties:
Attributes: SomeString
ResourceName: HelloWorldFunction
Type: AWS::Serverless::Function
Transform: AWS::Serverless-2016-10-31
What I want to do is to parse the Resources dynamically since the properties of the objects inside Resources are dependent of the property Type but cannot be implicated by the keys (such as AWSSNSTopic or AWSServerlessFunction which only happen to be consistent with the type in this case but do not have to).
So I tried to solve this somehow via #JsonSubTypes to track down the Type property and decide what type of POJO this will be mapped on. This could look like follows:
public class AWSLambdaResource {
#JsonProperty("AWSTemplateFormatVersion")
private String AWSTemplateFormatVersion;
#JsonProperty("Transform")
private String Transform;
#JsonProperty("Resources")
private Map<String, Ressource> Resources;
public String getAWSTemplateFormatVersion() {
return AWSTemplateFormatVersion;
}
public void setAWSTemplateFormatVersion(String AWSTemplateFormatVersion) {
this.AWSTemplateFormatVersion = AWSTemplateFormatVersion;
}
public String getTransform() {
return Transform;
}
public void setTransform(String Transform) {
this.Transform = Transform;
}
public Map<String, Ressource> getResources() {
return Resources;
}
public void setResources(Map<String, Ressource> resources) {
Resources = resources;
}
}
public class Ressource {
public ResourceInstance resourceInstance;
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "Type")
#JsonSubTypes({
#JsonSubTypes.Type(value = AWSServerlessFunction.class, name = "AWS::Serverless::Function"),
#JsonSubTypes.Type(value = AWSSNSTopic.class, name = "AWS::SNS::Topic")
})
public static class ResourceInstance {
#JsonProperty("Type")
public String type;
#JsonProperty("ResourceName")
public String resourceName;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getResourceName() {
return resourceName;
}
public void setResourceName(String resourceName) {
this.resourceName = resourceName;
}
}
#JsonTypeName("AWSServerlessFunction")
public static class AWSServerlessFunction extends ResourceInstance {
#JsonProperty("ResourceName")
private String resourceName;
#JsonProperty("Properties")
private Properties properties;
public static class Properties {
#JsonProperty("Attributes")
public String attributes;
public String getAttributes() {
return attributes;
}
public void setAttributes(String attributes) {
this.attributes = attributes;
}
}
public String getResourceName() {
return resourceName;
}
public void setResourceName(String resourceName) {
this.resourceName = resourceName;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
}
#JsonTypeName("AWSSNSTopic")
public static class AWSSNSTopic extends ResourceInstance {
#JsonProperty("Subscription")
public Subscription subscription;
public static class Subscription {
#JsonProperty("Endpoint")
public String endpoint;
#JsonProperty("Protocol")
public String protocol;
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
}
public Subscription getSubscription() {
return subscription;
}
public void setSubscription(Subscription subscription) {
this.subscription = subscription;
}
}
public ResourceInstance getResourceInstance() {
return resourceInstance;
}
public void setResourceInstance(ResourceInstance resourceInstance) {
this.resourceInstance = resourceInstance;
}
}
However, when I look into the map there are entries with keys AWSSNSTopic and AWSServerlessFunction but the corresponding resourceInstance objects are null.
Where did I go wrong? Or is this simply not possible to solve with this type of approach?

Access to class attributes' values using Java Annotations

I am working with a java example using annotations, I created a simple POJO (java bean) using annotations to its attributes. I want to have the ability to create new objects of this type and retrieve the values of its attributes using the annotations created.
My POJO :
import java.io.Serializable;
import annotations.BusinessObject;
import annotations.BusinessObjectAttribute;
import annotations.BusinessObjectName;
import annotations.BusinessObjectPolicy;
import annotations.BusinessObjectRevision;
import annotations.BusinessObjectVault;
#BusinessObject
public class IndusTask implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
// Mandatory to create new object !
#BusinessObjectName
private String taskName;
#BusinessObjectRevision
private String taskRevision;
#BusinessObjectVault
private String vault;
// Mandatory to invoke iTask.create(context, policy) in Database
#BusinessObjectPolicy
private String policy;
//Specific attributes
#BusinessObjectAttribute
private String taskDescription;
#BusinessObjectAttribute
private String creationDate;
#BusinessObjectAttribute
private Integer weight;
public IndusTask() {
}
public IndusTask(String taskName, String taskRevision, String vault, String policy, String taskDescription,
String creationDate, Integer weight) {
super();
this.taskName = taskName;
this.taskRevision = taskRevision;
this.vault = vault;
this.policy = policy;
this.taskDescription = taskDescription;
this.creationDate = creationDate;
this.weight = weight;
}
public String getTaskName() {
return taskName;
}
public void setTaskName(String taskName) {
this.taskName = taskName;
}
public String getTaskRevision() {
return taskRevision;
}
public void setTaskRevision(String taskRevision) {
this.taskRevision = taskRevision;
}
public String getVault() {
return vault;
}
public void setVault(String vault) {
this.vault = vault;
}
public String getTaskDescription() {
return taskDescription;
}
public void setTaskDescription(String taskDescription) {
this.taskDescription = taskDescription;
}
public String getCreationDate() {
return this.creationDate;
}
public void setCreationDate(String creationDate) {
this.creationDate = creationDate;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public String getPolicy() {
return policy;
}
public void setPolicy(String policy) {
this.policy = policy;
}
}
Example of attributes' declaration:
*Business Object Type declaration
package annotations;
import java.lang.annotation.*;
//#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface BusinessObject {
}
*Business Object Name Attribute:
package annotations;
import java.lang.annotation.*;
//#Target(ElementType.FIELD)
#Retention(RetentionPolicy.RUNTIME)
public #interface BusinessObjectName {
}
I Created a main to test if all the annotations are detected:
public class MainImpl {
public static void main(String[] args) {
// TODO Auto-generated method stub
IndusTask myTask = new IndusTask("mytstTask", "001", "eService Production", "TstTask Process",
"myTstTask Description", "2018/02/16#15:30:10:GMT", 200);
System.out.println(myTask.getClass().getAnnotations().length);
}
}
Output is displaying 1 ! so only the first annotation is detected !
I was told also that the object attributes values can be accessed using these annotation (something similar to) :
object.getClass().getAnnotations()
How can i do ?
You need to iterate through the fields, get their annotations and set the value wherever the annotation matches (it can match multiple fields):
#Retention(RetentionPolicy.RUNTIME)
public #interface Field1 {}
#Retention(RetentionPolicy.RUNTIME)
public #interface Field2 {}
public static class UnderTest {
#Field1
private String field1;
#Field2
private int field2;
public UnderTest(String field1, int field2) {
this.field1 = field1;
this.field2 = field2;
}
#Override
public String toString() {
return field1 + "=" + field2;
}
}
public static void setter(Object obj, Class<? extends Annotation> fieldAnnotation, Object fieldValue) throws IllegalAccessException {
for (Field field: obj.getClass().getDeclaredFields()) {
for (Annotation annot: field.getDeclaredAnnotations()) {
if (annot.annotationType().isAssignableFrom(fieldAnnotation)) {
if (!field.isAccessible()) {
field.setAccessible(true);
}
field.set(obj, fieldValue);
}
}
}
}
public static void main(String[] argv) throws IllegalAccessException {
UnderTest underTest = new UnderTest("A", 1);
System.out.println(underTest);
setter(underTest, Field1.class, "B");
setter(underTest, Field2.class, 2);
System.out.println(underTest);
}
Running this prints
A=1
B=2
Sounds like you're after the annotations on the fields too?
E.g. for the first private field:
myTask.getClass().getDeclaredFields()[0].getAnnotations()
Note depending how you're accessing a private field, you will sometimes also need to first ensure it is accessible:
...getDeclaredFields()[0].setAccessible(true);
[edit]
The values are reachable too from the fields. A basic worked example:
for (Field f : myTask.getClass().getDeclaredFields()) {
f.setAccessible(true);
System.out.println(f.getName() + "=" + f.get(myTask));
System.out.println(" annotations=" + java.util.Arrays.toString(f.getAnnotations()));
}

Custom Jackson Deserialization of a Generic Abstract class

I am having issues when trying to deserializing the following class:
public class MetricValuesDto {
private Map<MetricType, MetricValueDto<?>> metricValues;
public MetricValuesDto() {
}
public MetricValuesDto(Map<MetricType, MetricValueDto<?>> metricValues) {
this.metricValues = metricValues;
}
public Map<MetricType, MetricValueDto<?>> getMetricValues() {
return metricValues;
}
public void setMetricValues(Map<MetricType, MetricValueDto<?>> metricValues) {
this.metricValues = metricValues;
}
}
My generic abstract class:
public abstract class MetricValueDto<T> {
private T value;
private MetricTrend trend;
public MetricValueDto(T value, MetricTrend trend) {
this.value = value;
this.trend = trend;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public MetricTrend getTrend() {
return trend;
}
public void setTrend(MetricTrend trend) {
this.trend = trend;
}
}
I have two concrete classes which implement MetricValueDto:
IntMetricValueDto:
public class IntMetricValueDto extends MetricValueDto<Integer> {
public IntMetricValueDto(Integer value, MetricTrend trend) {
super(value, trend);
}
}
FloatMetricValueDto:
public class FloatMetricValueDto extends MetricValueDto<Float> {
public FloatMetricValueDto(Float value, MetricTrend trend) {
super(value, trend);
}
}
Any idea of what's the correct strategy to deserialize MetricValueDto so I can parse it through ObjectMapper or an RestTemplate? Whenever I run:
restTemplate.exchange("myEndpoint", HttpMethod.GET, entity, DataCollectionEventDto.class);
I get
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.resson.dto.MetricValueDto: abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
DataCollectionEventDto:
public class DataCollectionEventDto {
private List<MapLayerDto> mapLayers;
#JsonUnwrapped
private MetricValuesDto metricValues;
public List<MapLayerDto> getMapLayers() {
return mapLayers;
}
public void setMapLayers(List<MapLayerDto> mapLayers) {
this.mapLayers = mapLayers;
}
public MetricValuesDto getMetricValues() {
return metricValues;
}
public void setMetricValues(MetricValuesDto metricValues) {
this.metricValues = metricValues;
}
#Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
}
I have basically tried everything on web and I could not make it work; any suggestion would be helpful.
Use JsonSubTypes annotation with JsonTypeInfo to indicate subtypes. The property attribute JsonTypeInfo is used to differentiate between different subclasses.
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "typ")
#JsonSubTypes({
#JsonSubTypes.Type(value = IntMetricValueDto.class, name = "INT"),
#JsonSubTypes.Type(value = FloatMetricValueDto.class, name = "FLT")})
public abstract class MetricValueDto<T> {
private T value;
private MetricTrend trend;
...
}
While JsonTypeInfo works, and adds implementation-specific detail to the response, which later might add confusion to the API client.
I ended up implementing a custom StdDeserializer:
public class MetricValueDtoDeserializer<T> extends StdDeserializer<MetricValueDto<T>> {
private static final long serialVersionUID = 1L;
public MetricValueDtoDeserializer() {
this(null);
}
public MetricValueDtoDeserializer(Class<?> vc) {
super(vc);
}
private ObjectMapper mapper;
#Override
public MetricValueDto<T> deserialize(JsonParser jsonParser, DeserializationContext context)
throws IOException, JsonProcessingException {
String metricType = jsonParser.getCurrentName();
mapper = (ObjectMapper) jsonParser.getCodec();
ObjectNode objectNode = (ObjectNode) mapper.readTree(jsonParser);
Iterator<Entry<String, JsonNode>> elementsIterator = objectNode.fields();
Number number = null;
while (elementsIterator.hasNext()) {
Entry<String, JsonNode> element = elementsIterator.next();
String key = element.getKey();
if (key.equals("value")) {
number = parseValue(element, metricType);
}
if (key.equals("trend")) {
MetricTrend metricTrend = parseTrend(element);
return (produceMetricValueDto(number, metricTrend));
}
}
throw new IOException();
}
#SuppressWarnings("unchecked")
private MetricValueDto<T> produceMetricValueDto(Number number, MetricTrend metricTrend) throws IOException {
if (number instanceof Integer) {
return (MetricValueDto<T>) new IntMetricValueDto((Integer) number, metricTrend);
} else if (number instanceof Float) {
return (MetricValueDto<T>) new FloatMetricValueDto((Float) number, metricTrend);
}
throw new IOException();
}
private MetricTrend parseTrend(Entry<String, JsonNode> element)
throws JsonProcessingException {
String trend = mapper.treeToValue(element.getValue(), String.class);
if (trend == null) {
return null;
} else {
return MetricTrend.valueOf(trend);
}
}
private Number parseValue(Entry<String, JsonNode> element, String metricType)
throws IOException {
if (metricType.equals(MetricType.CANOPY_COVERAGE.toValue())
|| metricType.equals(MetricType.PLANT_SIZE.toValue())) {
return mapper.treeToValue(element.getValue(), Float.class);
} else if (metricType.equals(MetricType.INSECT_COUNT.toValue())
|| metricType.equals(MetricType.PLANT_COUNT.toValue())) {
return mapper.treeToValue(element.getValue(), Integer.class);
}
throw new IOException();
}
}
The code ended up to being more complex than JsonTypeInfo, but the API client is unaware of implementation-specific details.

Deserialize dynamic json using jackson JsonTypeInfo property as ENUM?

I am trying to get java object from dynamic JSON.
One Important point these given classes are from third party API.
#JsonTypeInfo(
use = Id.NAME,
include = As.PROPERTY,
property = "nodeType"
)
#JsonSubTypes({ #Type(
name = "Filter",
value = Filter.class
), #Type(
name = "Criterion",
value = Criterion.class
)})
public abstract class Node {
public Node() {
}
#JsonIgnore
public EvaluationResult evaluate(Map<UUID, List<AnswerValue>> answers) {
Evaluator evaluator = new Evaluator();
return evaluator.evaluateAdvancedLogic(this, answers);
}
}
Filter.java
#JsonInclude(Include.NON_NULL)
#JsonPropertyOrder({"evaluationType", "filters"})
public class Filter extends Node {
#JsonProperty("evaluationType")
private EvaluationType evaluationType;
#NotNull
#JsonProperty("filters")
#Valid
private List<Node> filters = new ArrayList();
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap();
public Filter() {
}
#JsonProperty("evaluationType")
public EvaluationType getEvaluationType() {
return this.evaluationType;
}
#JsonProperty("evaluationType")
public void setEvaluationType(EvaluationType evaluationType) {
this.evaluationType = evaluationType;
}
#JsonProperty("filters")
public List<Node> getFilters() {
return this.filters;
}
#JsonProperty("filters")
public void setFilters(List<Node> filters) {
this.filters = filters;
}
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
}
Criterion.java
#JsonInclude(Include.NON_NULL)
#JsonPropertyOrder({"fieldSourceType", "fieldCategoryName", "sequenceNumber", "fieldName", "values", "operator", "fieldId"})
public class Criterion extends Node {
#JsonProperty("fieldSourceType")
private FieldSourceType fieldSourceType;
#JsonProperty("fieldCategoryName")
private String fieldCategoryName;
#NotNull
#JsonProperty("sequenceNumber")
private Long sequenceNumber;
#JsonProperty("fieldName")
private String fieldName;
#JsonProperty("values")
#Valid
private List<String> values = new ArrayList();
#JsonProperty("operator")
#Valid
private Operator operator;
#NotNull
#JsonProperty("fieldId")
private UUID fieldId;
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap();
public Criterion() {
}
#JsonProperty("fieldSourceType")
public FieldSourceType getFieldSourceType() {
return this.fieldSourceType;
}
#JsonProperty("fieldSourceType")
public void setFieldSourceType(FieldSourceType fieldSourceType) {
this.fieldSourceType = fieldSourceType;
}
#JsonProperty("fieldCategoryName")
public String getFieldCategoryName() {
return this.fieldCategoryName;
}
#JsonProperty("fieldCategoryName")
public void setFieldCategoryName(String fieldCategoryName) {
this.fieldCategoryName = fieldCategoryName;
}
#JsonProperty("sequenceNumber")
public Long getSequenceNumber() {
return this.sequenceNumber;
}
#JsonProperty("sequenceNumber")
public void setSequenceNumber(Long sequenceNumber) {
this.sequenceNumber = sequenceNumber;
}
#JsonProperty("fieldName")
public String getFieldName() {
return this.fieldName;
}
#JsonProperty("fieldName")
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
#JsonProperty("values")
public List<String> getValues() {
return this.values;
}
#JsonProperty("values")
public void setValues(List<String> values) {
this.values = values;
}
#JsonProperty("operator")
public Operator getOperator() {
return this.operator;
}
#JsonProperty("operator")
public void setOperator(Operator operator) {
this.operator = operator;
}
#JsonProperty("fieldId")
public UUID getFieldId() {
return this.fieldId;
}
#JsonProperty("fieldId")
public void setFieldId(UUID fieldId) {
this.fieldId = fieldId;
}
}
The json used to conversion is this.
{
"evaluationType":"AND",
"nodeType":"Criterion",
"Criterion":[
{
"fieldName":"sdada",
"values":"sdad",
"operator":{
"operatorType":"Equals"
}
},
{
"nodeType":"Criterion",
"fieldName":"dasa",
"values":"das",
"operator":{
"operatorType":"Equals"
}
},
{
"nodeType":"Criterion",
"fieldName":"dada",
"values":"dads",
"operator":{
"operatorType":"Equals"
}
}
]
}
The problem is that deserialization of this JSON fails with following error:
{
"message": "Class com.cvent.logic.model.Criterion is not assignable to com.cvent.logic.model.Filter"
}
The first part of the JSON is wrong
{
"evaluationType":"AND",
"nodeType":"Criterion",
"Criterion":[
It says that the type is Criterion but it has evaluationType from Filter.
Also, probably "Criterion" : [ should be "filters" : [

Categories