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 | 41 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; |
42 | 42 | import org.thingsboard.server.common.transport.util.SslUtil; |
43 | 43 | import org.thingsboard.server.gen.transport.TransportProtos; |
44 | +import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; | |
44 | 45 | import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; |
45 | 46 | import org.thingsboard.server.transport.lwm2m.secure.credentials.LwM2MCredentials; |
46 | 47 | import org.thingsboard.server.common.data.device.credentials.lwm2m.X509ClientCredentials; |
... | ... | @@ -61,6 +62,7 @@ import java.util.concurrent.TimeUnit; |
61 | 62 | |
62 | 63 | @Slf4j |
63 | 64 | @Component |
65 | +@TbLwM2mTransportComponent | |
64 | 66 | @RequiredArgsConstructor |
65 | 67 | public class TbLwM2MDtlsCertificateVerifier implements NewAdvancedCertificateVerifier { |
66 | 68 | ... | ... |
... | ... | @@ -228,29 +228,27 @@ public class JsonConverter { |
228 | 228 | private static KeyValueProto buildNumericKeyValueProto(JsonPrimitive value, String key) { |
229 | 229 | String valueAsString = value.getAsString(); |
230 | 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 | 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 | 254 | public static TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(JsonElement json, int requestId) throws JsonSyntaxException { |
... | ... | @@ -261,27 +259,24 @@ public class JsonConverter { |
261 | 259 | private static void parseNumericValue(List<KvEntry> result, Entry<String, JsonElement> valueEntry, JsonPrimitive value) { |
262 | 260 | String valueAsString = value.getAsString(); |
263 | 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 | 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 | 15 | */ |
16 | 16 | |
17 | 17 | import com.google.gson.JsonParser; |
18 | +import com.google.gson.JsonSyntaxException; | |
18 | 19 | import org.junit.Assert; |
20 | +import org.junit.Before; | |
19 | 21 | import org.junit.Test; |
20 | 22 | import org.junit.runner.RunWith; |
21 | 23 | import org.mockito.junit.MockitoJUnitRunner; |
... | ... | @@ -28,6 +30,11 @@ public class JsonConverterTest { |
28 | 30 | |
29 | 31 | private static final JsonParser JSON_PARSER = new JsonParser(); |
30 | 32 | |
33 | + @Before | |
34 | + public void before() { | |
35 | + JsonConverter.setTypeCastEnabled(true); | |
36 | + } | |
37 | + | |
31 | 38 | @Test |
32 | 39 | public void testParseBigDecimalAsLong() { |
33 | 40 | var result = JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 1E+1}"), 0L); |
... | ... | @@ -58,4 +65,33 @@ public class JsonConverterTest { |
58 | 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 | } | ... | ... |