Commit c83c232166f4ec19e250eea7f1146a7e02ad31d0

Authored by YevhenBondarenko
Committed by Andrew Shvayka
1 parent 2086bd2d

JsonConverter improvements (correct value conversion)

... ... @@ -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 }
... ...