16
16
* Converts between {@link Object} properties and byte arrays using FlexBuffers.
17
17
* <p>
18
18
* Types are limited to those supported by FlexBuffers, including that map keys must be {@link String}.
19
+ * (There are subclasses available that auto-convert {@link Integer} and {@link Long} key maps,
20
+ * see {@link #convertToKey}.)
19
21
* <p>
20
- * Regardless of the stored type, integers are restored as {@link Long} if the value does not fit {@link Integer},
21
- * otherwise as {@link Integer}. So e.g. when storing a {@link Long} value of {@code 1L}, the value restored from the
22
+ * If any item requires 64 bits for storage in the FlexBuffers Map/Vector (a large Long, a Double)
23
+ * all integers are restored as {@link Long}, otherwise {@link Integer}.
24
+ * So e.g. when storing only a {@link Long} value of {@code 1L}, the value restored from the
22
25
* database will be of type {@link Integer}.
26
+ * (There are subclasses available that always restore as {@link Long}, see {@link #shouldRestoreAsLong}.)
23
27
* <p>
24
28
* Values of type {@link Float} are always restored as {@link Double}.
25
29
* Cast to {@link Float} to obtain the original value.
@@ -85,6 +89,15 @@ private void addValue(FlexBuffersBuilder builder, Object value) {
85
89
}
86
90
}
87
91
92
+ /**
93
+ * Checks Java map key is of the expected type, otherwise throws.
94
+ */
95
+ protected void checkMapKeyType (Object rawKey ) {
96
+ if (!(rawKey instanceof String )) {
97
+ throw new IllegalArgumentException ("Map keys must be String" );
98
+ }
99
+ }
100
+
88
101
private void addMap (FlexBuffersBuilder builder , String mapKey , Map <Object , Object > map ) {
89
102
int mapStart = builder .startMap ();
90
103
@@ -94,9 +107,7 @@ private void addMap(FlexBuffersBuilder builder, String mapKey, Map<Object, Objec
94
107
if (rawKey == null || value == null ) {
95
108
throw new IllegalArgumentException ("Map keys or values must not be null" );
96
109
}
97
- if (!(rawKey instanceof String )) {
98
- throw new IllegalArgumentException ("Map keys must be String" );
99
- }
110
+ checkMapKeyType (rawKey );
100
111
String key = rawKey .toString ();
101
112
if (value instanceof Map ) {
102
113
//noinspection unchecked
@@ -189,13 +200,22 @@ public Object convertToEntityProperty(byte[] databaseValue) {
189
200
}
190
201
}
191
202
203
+ /**
204
+ * Converts a FlexBuffers string map key to the Java map key (e.g. String to Integer).
205
+ * <p>
206
+ * This required conversion restricts all keys (root and embedded maps) to the same type.
207
+ */
208
+ Object convertToKey (String keyValue ) {
209
+ return keyValue ;
210
+ }
211
+
192
212
/**
193
213
* Returns true if the width in bytes stored in the private parentWidth field of FlexBuffers.Reference is 8.
194
214
* Note: FlexBuffers stores all items in a map/vector using the size of the widest item. However,
195
215
* an item's size is only as wide as needed, e.g. a 64-bit integer (Java Long, 8 bytes) will be
196
216
* reduced to 1 byte if it does not exceed its value range.
197
217
*/
198
- private boolean shouldRestoreAsLong (FlexBuffers .Reference reference ) {
218
+ protected boolean shouldRestoreAsLong (FlexBuffers .Reference reference ) {
199
219
try {
200
220
Field parentWidthF = reference .getClass ().getDeclaredField ("parentWidth" );
201
221
parentWidthF .setAccessible (true );
@@ -217,7 +237,8 @@ private Map<Object, Object> buildMap(FlexBuffers.Map map) {
217
237
// So set initial capacity based on default load factor 0.75 accordingly.
218
238
Map <Object , Object > resultMap = new HashMap <>((int ) (entryCount / 0.75 + 1 ));
219
239
for (int i = 0 ; i < entryCount ; i ++) {
220
- String key = keys .get (i ).toString ();
240
+ String rawKey = keys .get (i ).toString ();
241
+ Object key = convertToKey (rawKey );
221
242
FlexBuffers .Reference value = values .get (i );
222
243
if (value .isMap ()) {
223
244
resultMap .put (key , buildMap (value .asMap ()));
0 commit comments