Commit c83c232166f4ec19e250eea7f1146a7e02ad31d0
Committed by
Andrew Shvayka
1 parent
2086bd2d
JsonConverter improvements (correct value conversion)
Showing
3 changed files
with
69 additions
and
36 deletions
@@ -41,6 +41,7 @@ import org.thingsboard.server.common.transport.TransportServiceCallback; | @@ -41,6 +41,7 @@ import org.thingsboard.server.common.transport.TransportServiceCallback; | ||
41 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; | 41 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; |
42 | import org.thingsboard.server.common.transport.util.SslUtil; | 42 | import org.thingsboard.server.common.transport.util.SslUtil; |
43 | import org.thingsboard.server.gen.transport.TransportProtos; | 43 | import org.thingsboard.server.gen.transport.TransportProtos; |
44 | +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | ||
44 | import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; | 45 | import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; |
45 | import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; | 46 | import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; |
46 | import org.thingsboard.server.common.data.device.credentials.lwm2m.X509ClientCredentials; | 47 | import org.thingsboard.server.common.data.device.credentials.lwm2m.X509ClientCredentials; |
@@ -61,6 +62,7 @@ import java.util.concurrent.TimeUnit; | @@ -61,6 +62,7 @@ import java.util.concurrent.TimeUnit; | ||
61 | 62 | ||
62 | @Slf4j | 63 | @Slf4j |
63 | @Component | 64 | @Component |
65 | +@TbLwM2mTransportComponent | ||
64 | @RequiredArgsConstructor | 66 | @RequiredArgsConstructor |
65 | public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVerifier { | 67 | public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVerifier { |
66 | 68 |
@@ -228,29 +228,27 @@ public class JsonConverter { | @@ -228,29 +228,27 @@ public class JsonConverter { | ||
228 | private static KeyValueProto buildNumericKeyValueProto(JsonPrimitive value, String key) { | 228 | private static KeyValueProto buildNumericKeyValueProto(JsonPrimitive value, String key) { |
229 | String valueAsString = value.getAsString(); | 229 | String valueAsString = value.getAsString(); |
230 | KeyValueProto.Builder builder = KeyValueProto.newBuilder().setKey(key); | 230 | KeyValueProto.Builder builder = KeyValueProto.newBuilder().setKey(key); |
231 | - if (valueAsString.contains("e") || valueAsString.contains("E")) { | ||
232 | - //TODO: correct value conversion. We should make sure that if the value can't fit into Long or Double, we should send String | ||
233 | - var bd = new BigDecimal(valueAsString); | ||
234 | - if (bd.stripTrailingZeros().scale() <= 0) { | ||
235 | - try { | ||
236 | - return builder.setType(KeyValueType.LONG_V).setLongV(bd.longValueExact()).build(); | ||
237 | - } catch (ArithmeticException e) { | ||
238 | - return builder.setType(KeyValueType.DOUBLE_V).setDoubleV(bd.doubleValue()).build(); | 231 | + var bd = new BigDecimal(valueAsString); |
232 | + if (bd.stripTrailingZeros().scale() <= 0) { | ||
233 | + try { | ||
234 | + return builder.setType(KeyValueType.LONG_V).setLongV(bd.longValueExact()).build(); | ||
235 | + } catch (ArithmeticException e) { | ||
236 | + if (isTypeCastEnabled) { | ||
237 | + return builder.setType(KeyValueType.STRING_V).setStringV(bd.toPlainString()).build(); | ||
238 | + } else { | ||
239 | + throw new JsonSyntaxException("Big integer values are not supported!"); | ||
239 | } | 240 | } |
240 | - } else { | ||
241 | - return builder.setType(KeyValueType.DOUBLE_V).setDoubleV(bd.doubleValue()).build(); | ||
242 | } | 241 | } |
243 | - } else if (valueAsString.contains(".")) { | ||
244 | - return builder.setType(KeyValueType.DOUBLE_V).setDoubleV(value.getAsDouble()).build(); | ||
245 | } else { | 242 | } else { |
246 | - try { | ||
247 | - long longValue = Long.parseLong(value.getAsString()); | ||
248 | - return builder.setType(KeyValueType.LONG_V).setLongV(longValue).build(); | ||
249 | - } catch (NumberFormatException e) { | ||
250 | - //TODO: correct value conversion. We should make sure that if the value can't fit into Long or Double, we should send String | ||
251 | - return builder.setType(KeyValueType.DOUBLE_V).setDoubleV(new BigDecimal(valueAsString).doubleValue()).build(); | 243 | + if (bd.scale() <= 16) { |
244 | + return builder.setType(KeyValueType.DOUBLE_V).setDoubleV(bd.doubleValue()).build(); | ||
245 | + } else if (isTypeCastEnabled) { | ||
246 | + return builder.setType(KeyValueType.STRING_V).setStringV(bd.toPlainString()).build(); | ||
247 | + } else { | ||
248 | + throw new JsonSyntaxException("Big integer values are not supported!"); | ||
252 | } | 249 | } |
253 | } | 250 | } |
251 | + | ||
254 | } | 252 | } |
255 | 253 | ||
256 | public static TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(JsonElement json, int requestId) throws JsonSyntaxException { | 254 | public static TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(JsonElement json, int requestId) throws JsonSyntaxException { |
@@ -261,27 +259,24 @@ public class JsonConverter { | @@ -261,27 +259,24 @@ public class JsonConverter { | ||
261 | private static void parseNumericValue(List<KvEntry> result, Entry<String, JsonElement> valueEntry, JsonPrimitive value) { | 259 | private static void parseNumericValue(List<KvEntry> result, Entry<String, JsonElement> valueEntry, JsonPrimitive value) { |
262 | String valueAsString = value.getAsString(); | 260 | String valueAsString = value.getAsString(); |
263 | String key = valueEntry.getKey(); | 261 | String key = valueEntry.getKey(); |
264 | - if (valueAsString.contains("e") || valueAsString.contains("E")) { | ||
265 | - //TODO: correct value conversion. We should make sure that if the value can't fit into Long or Double, we should send String | ||
266 | - var bd = new BigDecimal(valueAsString); | ||
267 | - if (bd.stripTrailingZeros().scale() <= 0) { | ||
268 | - try { | ||
269 | - result.add(new LongDataEntry(key, bd.longValueExact())); | ||
270 | - } catch (ArithmeticException e) { | ||
271 | - result.add(new DoubleDataEntry(key, bd.doubleValue())); | 262 | + var bd = new BigDecimal(valueAsString); |
263 | + if (bd.stripTrailingZeros().scale() <= 0) { | ||
264 | + try { | ||
265 | + result.add(new LongDataEntry(key, bd.longValueExact())); | ||
266 | + } catch (ArithmeticException e) { | ||
267 | + if (isTypeCastEnabled) { | ||
268 | + result.add(new StringDataEntry(key, bd.toPlainString())); | ||
269 | + } else { | ||
270 | + throw new JsonSyntaxException("Big integer values are not supported!"); | ||
272 | } | 271 | } |
273 | - } else { | ||
274 | - result.add(new DoubleDataEntry(key, bd.doubleValue())); | ||
275 | } | 272 | } |
276 | - } else if (valueAsString.contains(".")) { | ||
277 | - result.add(new DoubleDataEntry(key, value.getAsDouble())); | ||
278 | } else { | 273 | } else { |
279 | - try { | ||
280 | - long longValue = Long.parseLong(value.getAsString()); | ||
281 | - result.add(new LongDataEntry(key, longValue)); | ||
282 | - } catch (NumberFormatException e) { | ||
283 | - //TODO: correct value conversion. We should make sure that if the value can't fit into Long or Double, we should send String | ||
284 | - result.add(new DoubleDataEntry(key, new BigDecimal(valueAsString).doubleValue())); | 274 | + if (bd.scale() <= 16) { |
275 | + result.add(new DoubleDataEntry(key, bd.doubleValue())); | ||
276 | + } else if (isTypeCastEnabled) { | ||
277 | + result.add(new StringDataEntry(key, bd.toPlainString())); | ||
278 | + } else { | ||
279 | + throw new JsonSyntaxException("Big integer values are not supported!"); | ||
285 | } | 280 | } |
286 | } | 281 | } |
287 | } | 282 | } |
@@ -15,7 +15,9 @@ | @@ -15,7 +15,9 @@ | ||
15 | */ | 15 | */ |
16 | 16 | ||
17 | import com.google.gson.JsonParser; | 17 | import com.google.gson.JsonParser; |
18 | +import com.google.gson.JsonSyntaxException; | ||
18 | import org.junit.Assert; | 19 | import org.junit.Assert; |
20 | +import org.junit.Before; | ||
19 | import org.junit.Test; | 21 | import org.junit.Test; |
20 | import org.junit.runner.RunWith; | 22 | import org.junit.runner.RunWith; |
21 | import org.mockito.junit.MockitoJUnitRunner; | 23 | import org.mockito.junit.MockitoJUnitRunner; |
@@ -28,6 +30,11 @@ public class JsonConverterTest { | @@ -28,6 +30,11 @@ public class JsonConverterTest { | ||
28 | 30 | ||
29 | private static final JsonParser JSON_PARSER = new JsonParser(); | 31 | private static final JsonParser JSON_PARSER = new JsonParser(); |
30 | 32 | ||
33 | + @Before | ||
34 | + public void before() { | ||
35 | + JsonConverter.setTypeCastEnabled(true); | ||
36 | + } | ||
37 | + | ||
31 | @Test | 38 | @Test |
32 | public void testParseBigDecimalAsLong() { | 39 | public void testParseBigDecimalAsLong() { |
33 | var result = JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 1E+1}"), 0L); | 40 | var result = JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 1E+1}"), 0L); |
@@ -58,4 +65,33 @@ public class JsonConverterTest { | @@ -58,4 +65,33 @@ public class JsonConverterTest { | ||
58 | Assert.assertEquals(11L, result.get(0L).get(0).getLongValue().get().longValue()); | 65 | Assert.assertEquals(11L, result.get(0L).get(0).getLongValue().get().longValue()); |
59 | } | 66 | } |
60 | 67 | ||
68 | + @Test | ||
69 | + public void testParseBigDecimalAsStringOutOfLongRange() { | ||
70 | + var result = JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 9.9701010061400066E19}"), 0L); | ||
71 | + Assert.assertEquals("99701010061400066000", result.get(0L).get(0).getStrValue().get()); | ||
72 | + } | ||
73 | + | ||
74 | + @Test | ||
75 | + public void testParseBigDecimalAsStringOutOfLongRange2() { | ||
76 | + var result = JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 99701010061400066001}"), 0L); | ||
77 | + Assert.assertEquals("99701010061400066001", result.get(0L).get(0).getStrValue().get()); | ||
78 | + } | ||
79 | + | ||
80 | + @Test | ||
81 | + public void testParseBigDecimalAsStringOutOfLongRange3() { | ||
82 | + var result = JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 1E19}"), 0L); | ||
83 | + Assert.assertEquals("10000000000000000000", result.get(0L).get(0).getStrValue().get()); | ||
84 | + } | ||
85 | + | ||
86 | + @Test(expected = JsonSyntaxException.class) | ||
87 | + public void testParseBigDecimalOutOfLongRangeWithoutParsing() { | ||
88 | + JsonConverter.setTypeCastEnabled(false); | ||
89 | + JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 89701010051400054084}"), 0L); | ||
90 | + } | ||
91 | + | ||
92 | + @Test(expected = JsonSyntaxException.class) | ||
93 | + public void testParseBigDecimalOutOfLongRangeWithoutParsing2() { | ||
94 | + JsonConverter.setTypeCastEnabled(false); | ||
95 | + JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 9.9701010061400066E19}"), 0L); | ||
96 | + } | ||
61 | } | 97 | } |