Commit 302c0d25f2c9ce1e796272d54bf277332096dc66
1 parent
2c012f58
Rework generic entity serialization using custom json serializers instead of json converter
Showing
6 changed files
with
199 additions
and
2 deletions
services/Common/src/main/java/de/bht/beuthbot/persistence/GenericEntityAccessFacade.java
... | ... | @@ -8,6 +8,8 @@ import de.bht.beuthbot.model.entities.GenericEntityAttribute; |
8 | 8 | import de.bht.beuthbot.model.entities.GenericEntityAttributeValue; |
9 | 9 | |
10 | 10 | import java.io.IOException; |
11 | +import java.io.StringWriter; | |
12 | +import java.io.Writer; | |
11 | 13 | import java.util.List; |
12 | 14 | import java.util.stream.Collectors; |
13 | 15 | |
... | ... | @@ -29,9 +31,9 @@ public class GenericEntityAccessFacade { |
29 | 31 | String propertyAsJson; |
30 | 32 | |
31 | 33 | if (isPrimitiveOrWrapperAttributeType(attributeType)) { |
32 | - propertyAsJson = GenericEntityJsonConverter.toJson(property.getFirstValueOrNull()); | |
34 | + propertyAsJson = writeGenericHierarchyToJson(property.getFirstValueOrNull()); | |
33 | 35 | } else { |
34 | - propertyAsJson = GenericEntityJsonConverter.toJson(property); | |
36 | + propertyAsJson = writeGenericHierarchyToJson(property); | |
35 | 37 | } |
36 | 38 | |
37 | 39 | return (T) JsonHelper.fromJson(propertyAsJson, attributeType); |
... | ... | @@ -90,4 +92,17 @@ public class GenericEntityAccessFacade { |
90 | 92 | |
91 | 93 | return mapper.readValue(json, type); |
92 | 94 | } |
95 | + | |
96 | + private static String writeGenericHierarchyToJson(Object value) throws IOException { | |
97 | + ObjectMapper mapper = new ObjectMapper(); | |
98 | + SimpleModule module = new SimpleModule(); | |
99 | + module.addSerializer(GenericEntity.class, new GenericEntitySerializer()); | |
100 | + module.addSerializer(GenericEntityAttribute.class, new GenericEntityAttributeSerializer()); | |
101 | + module.addSerializer(GenericEntityAttributeValue.class, new GenericEntityAttributeValueSerializer()); | |
102 | + mapper.registerModule(module); | |
103 | + | |
104 | + Writer stringWriter = new StringWriter(); | |
105 | + mapper.writeValue(stringWriter, value); | |
106 | + return stringWriter.toString(); | |
107 | + } | |
93 | 108 | } | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/persistence/GenericEntityAttributeSerializer.java
0 → 100644
1 | +package de.bht.beuthbot.persistence; | |
2 | + | |
3 | +import com.fasterxml.jackson.core.JsonGenerationException; | |
4 | +import com.fasterxml.jackson.core.JsonGenerator; | |
5 | +import com.fasterxml.jackson.databind.SerializerProvider; | |
6 | +import com.fasterxml.jackson.databind.ser.std.StdSerializer; | |
7 | +import de.bht.beuthbot.model.entities.GenericEntityAttribute; | |
8 | +import de.bht.beuthbot.model.entities.GenericEntityAttributeValue; | |
9 | + | |
10 | +import java.io.IOException; | |
11 | +import java.util.List; | |
12 | + | |
13 | +/** | |
14 | + * Created by Benjamin Rühl on 14.01.2018. | |
15 | + */ | |
16 | +public class GenericEntityAttributeSerializer extends StdSerializer<GenericEntityAttribute> { | |
17 | + | |
18 | + private GenericEntityAttributeValueSerializer attributeValueSerializer = new GenericEntityAttributeValueSerializer(); | |
19 | + | |
20 | + public GenericEntityAttributeSerializer() { | |
21 | + this(GenericEntityAttribute.class); | |
22 | + } | |
23 | + | |
24 | + public GenericEntityAttributeSerializer(Class<GenericEntityAttribute> t) { | |
25 | + super(t); | |
26 | + } | |
27 | + | |
28 | + @Override | |
29 | + public void serialize(GenericEntityAttribute value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException { | |
30 | + List<GenericEntityAttributeValue> attributeValues = value.getValues(); | |
31 | + | |
32 | + jgen.writeStartObject(); | |
33 | + jgen.writeFieldName(value.getName()); | |
34 | + | |
35 | + if (attributeValues == null || attributeValues.isEmpty()) { | |
36 | + jgen.writeNullField(value.getName()); | |
37 | + } else if (attributeValues.size() == 1) { | |
38 | + attributeValueSerializer.serialize(value.getValues().get(0), jgen, provider); | |
39 | + } else { | |
40 | + jgen.writeArrayFieldStart(value.getName()); | |
41 | + | |
42 | + for (GenericEntityAttributeValue genericValue : value.getValues()) { | |
43 | + attributeValueSerializer.serialize(genericValue, jgen, provider); | |
44 | + } | |
45 | + | |
46 | + jgen.writeEndArray(); | |
47 | + } | |
48 | + | |
49 | + jgen.writeEndObject(); | |
50 | + } | |
51 | +} | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/persistence/GenericEntityAttributeValueSerializer.java
0 → 100644
1 | +package de.bht.beuthbot.persistence; | |
2 | + | |
3 | +import com.fasterxml.jackson.core.JsonGenerationException; | |
4 | +import com.fasterxml.jackson.core.JsonGenerator; | |
5 | +import com.fasterxml.jackson.databind.SerializerProvider; | |
6 | +import com.fasterxml.jackson.databind.ser.std.StdSerializer; | |
7 | +import de.bht.beuthbot.model.entities.GenericEntityAttributeValue; | |
8 | + | |
9 | +import java.io.IOException; | |
10 | + | |
11 | +/** | |
12 | + * Created by Benjamin Rühl on 14.01.2018. | |
13 | + */ | |
14 | +public class GenericEntityAttributeValueSerializer extends StdSerializer<GenericEntityAttributeValue> { | |
15 | + | |
16 | + public GenericEntityAttributeValueSerializer() { | |
17 | + this(GenericEntityAttributeValue.class); | |
18 | + } | |
19 | + | |
20 | + public GenericEntityAttributeValueSerializer(Class<GenericEntityAttributeValue> t) { | |
21 | + super(t); | |
22 | + } | |
23 | + | |
24 | + @Override | |
25 | + public void serialize(GenericEntityAttributeValue value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException { | |
26 | + if (value.getValueAsBool() != null) { | |
27 | + jgen.writeBoolean(value.getValueAsBool()); | |
28 | + } else if (value.getValueAsLong() != null) { | |
29 | + jgen.writeNumber(value.getValueAsLong()); | |
30 | + } else if (value.getValueAsDouble() != null) { | |
31 | + jgen.writeNumber(value.getValueAsDouble()); | |
32 | + } else if (value.getValueAsString() != null) { | |
33 | + jgen.writeString(value.getValueAsString()); | |
34 | + } else if (value.getValueAsEntity() != null) { | |
35 | + new GenericEntitySerializer().serialize(value.getValueAsEntity(), jgen, provider); | |
36 | + } | |
37 | + } | |
38 | +} | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/persistence/GenericEntityJsonConverter.java
... | ... | @@ -18,6 +18,7 @@ import java.util.List; |
18 | 18 | /** |
19 | 19 | * Created by Benjamin Rühl on 22.12.2017. |
20 | 20 | * Helper class to serialize GenericEntity as if its generic attributes were normal fields |
21 | + * @deprecated replaced by generic entity serializers | |
21 | 22 | */ |
22 | 23 | public class GenericEntityJsonConverter { |
23 | 24 | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/persistence/GenericEntitySerializer.java
0 → 100644
1 | +package de.bht.beuthbot.persistence; | |
2 | + | |
3 | +import com.fasterxml.jackson.core.JsonGenerationException; | |
4 | +import com.fasterxml.jackson.core.JsonGenerator; | |
5 | +import com.fasterxml.jackson.databind.SerializerProvider; | |
6 | +import com.fasterxml.jackson.databind.ser.std.StdSerializer; | |
7 | +import de.bht.beuthbot.model.entities.GenericEntity; | |
8 | +import de.bht.beuthbot.model.entities.GenericEntityAttribute; | |
9 | +import de.bht.beuthbot.model.entities.GenericEntityAttributeValue; | |
10 | + | |
11 | +import java.io.IOException; | |
12 | +import java.lang.reflect.Field; | |
13 | +import java.lang.reflect.ParameterizedType; | |
14 | +import java.lang.reflect.Type; | |
15 | +import java.util.Arrays; | |
16 | +import java.util.List; | |
17 | + | |
18 | +/** | |
19 | + * Created by Benjamin Rühl on 14.01.2018. | |
20 | + */ | |
21 | +public class GenericEntitySerializer extends StdSerializer<GenericEntity> { | |
22 | + | |
23 | + private GenericEntityAttributeSerializer attributeSerializer = new GenericEntityAttributeSerializer(); | |
24 | + | |
25 | + public GenericEntitySerializer() { | |
26 | + this(GenericEntity.class); | |
27 | + } | |
28 | + | |
29 | + public GenericEntitySerializer(Class<GenericEntity> t) { | |
30 | + super(t); | |
31 | + } | |
32 | + | |
33 | + /** | |
34 | + * Uses a JsonGenerator to append a GenericEntity and its content to json. | |
35 | + * Does not open the json object because this part depends on whether the object stands for itself or is the value of a field. | |
36 | + * However it does close the object. | |
37 | + * @throws IOException | |
38 | + */ | |
39 | + @Override | |
40 | + public void serialize(GenericEntity value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException { | |
41 | + jgen.writeStartObject(); | |
42 | + | |
43 | + writeClassFieldsWithoutGenericEntityHierarchy(jgen, value); | |
44 | + | |
45 | + for (GenericEntityAttribute genericAttribute : value.getAttributes()) { | |
46 | + attributeSerializer.serialize(genericAttribute, jgen, provider); | |
47 | + } | |
48 | + | |
49 | + jgen.writeEndObject(); | |
50 | + } | |
51 | + | |
52 | + /** | |
53 | + * Uses a JsonGenerator to append all fields and their values of the targetObject to json. | |
54 | + * Ignores fields that have GenericEntity, GenericEntityAttribute or GenericEntityAttributeValue as type or generic list parameter. | |
55 | + * @throws IOException | |
56 | + */ | |
57 | + private void writeClassFieldsWithoutGenericEntityHierarchy(JsonGenerator jsonGenerator, Object targetObject) throws IOException { | |
58 | + for (Field field : targetObject.getClass().getFields()) { | |
59 | + if (isGenericEntityHierarchyType(field)) | |
60 | + continue; | |
61 | + | |
62 | + try { | |
63 | + jsonGenerator.writeObjectField(field.getName(), field.get(targetObject)); | |
64 | + } catch (Exception e) { | |
65 | + jsonGenerator.writeStringField(field.getName(), e.getClass().getName()); | |
66 | + e.printStackTrace(); | |
67 | + } | |
68 | + } | |
69 | + } | |
70 | + | |
71 | + /** | |
72 | + * Determines whether the field's type is GenericEntity, GenericEntityAttribute or GenericEntityAttributeValue | |
73 | + * or a list type with one of those types as generic type parameter. | |
74 | + */ | |
75 | + private boolean isGenericEntityHierarchyType(Field field) { | |
76 | + List<Class> typesOfGenericEntityHierarchy = Arrays.asList(GenericEntity.class, GenericEntityAttribute.class, GenericEntityAttributeValue.class); | |
77 | + | |
78 | + // check for list types | |
79 | + try { | |
80 | + if (Iterable.class.isAssignableFrom(field.getType())) { | |
81 | + Type fieldFirstGenericType = ((ParameterizedType)field.getGenericType()).getActualTypeArguments()[0]; | |
82 | + if (typesOfGenericEntityHierarchy.contains(fieldFirstGenericType.getClass())) | |
83 | + return true; | |
84 | + } | |
85 | + } catch (Exception e) { | |
86 | + // not a list or not generic | |
87 | + } | |
88 | + | |
89 | + return typesOfGenericEntityHierarchy.contains(field.getType()); | |
90 | + } | |
91 | +} | ... | ... |
services/Common/src/main/java/de/bht/beuthbot/persistence/JsonMapUserType.java
... | ... | @@ -18,6 +18,7 @@ import java.util.Map; |
18 | 18 | /** |
19 | 19 | * Created by Benjamin Rühl on 03.12.2017. |
20 | 20 | * Custom Hibernate UserType for mapping json typed columns in postgres to java maps |
21 | + * @deprecated Currently not in use | |
21 | 22 | * @see <a href="http://vojtechruzicka.com/postgresqls-jsonb-type-mapping-using-hibernate/">vojtechruzicka.com</a> |
22 | 23 | */ |
23 | 24 | public class JsonMapUserType implements UserType { | ... | ... |