Skip to content

Commit

Permalink
GH-1619: fix Precision loss with SenMLJSON and Old JSON content Format.
Browse files Browse the repository at this point in the history
  • Loading branch information
sbernard31 committed May 30, 2024
1 parent a7fb3d6 commit d876b69
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.eclipse.leshan.core.json.LwM2mJsonException;
import org.eclipse.leshan.core.util.json.JsonException;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.cfg.JsonNodeFeature;

Expand All @@ -33,9 +34,22 @@
*/
public class LwM2mJsonJacksonEncoderDecoder implements LwM2mJsonDecoder, LwM2mJsonEncoder {

private static final JsonRootObjectSerDes serDes = new JsonRootObjectSerDes();
private static final ObjectMapper mapper = new ObjectMapper()
.configure(JsonNodeFeature.STRIP_TRAILING_BIGDECIMAL_ZEROES, false);
private final JsonRootObjectSerDes serDes;
private final ObjectMapper mapper;

public LwM2mJsonJacksonEncoderDecoder() {
this(new JsonRootObjectSerDes(), null);
}

public LwM2mJsonJacksonEncoderDecoder(JsonRootObjectSerDes serDes, ObjectMapper objectMapper) {
this.serDes = serDes;
this.mapper = objectMapper == null ? createDefaultObjectMapper() : objectMapper;
}

protected ObjectMapper createDefaultObjectMapper() {
return new ObjectMapper().configure(JsonNodeFeature.STRIP_TRAILING_BIGDECIMAL_ZEROES, false)
.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true);
}

@Override
public String toJsonLwM2m(JsonRootObject jro) throws LwM2mJsonException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.eclipse.leshan.senml.SenMLPack;
import org.eclipse.leshan.senml.SenMLRecord;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.cfg.JsonNodeFeature;
Expand All @@ -41,8 +42,7 @@
*/
public class SenMLJsonJacksonEncoderDecoder implements SenMLDecoder, SenMLEncoder {
private final JacksonJsonSerDes<SenMLRecord> serDes;
private static final ObjectMapper mapper = new ObjectMapper()
.configure(JsonNodeFeature.STRIP_TRAILING_BIGDECIMAL_ZEROES, false);
private final ObjectMapper mapper;

public SenMLJsonJacksonEncoderDecoder() {
this(false);
Expand All @@ -68,7 +68,18 @@ public SenMLJsonJacksonEncoderDecoder(boolean allowNoValue, Base64Decoder base64
}

public SenMLJsonJacksonEncoderDecoder(JacksonJsonSerDes<SenMLRecord> senMLJSONSerializerDeserializer) {
this(senMLJSONSerializerDeserializer, null);
}

public SenMLJsonJacksonEncoderDecoder(JacksonJsonSerDes<SenMLRecord> senMLJSONSerializerDeserializer,
ObjectMapper objectMapper) {
this.serDes = senMLJSONSerializerDeserializer;
this.mapper = objectMapper == null ? createDefaultObjectMapper() : objectMapper;
}

protected ObjectMapper createDefaultObjectMapper() {
return new ObjectMapper().configure(JsonNodeFeature.STRIP_TRAILING_BIGDECIMAL_ZEROES, false)
.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public void deserialize_device_object() throws LwM2mJsonException {
b.append("{\"n\":\"9\",\"v\":100},");
b.append("{\"n\":\"10\",\"v\":15},");
b.append("{\"n\":\"11/0\",\"v\":0},");
b.append("{\"n\":\"13\",\"v\":1.367491215E9},");
b.append("{\"n\":\"13\",\"v\":1367491215},");
b.append("{\"n\":\"14\",\"sv\":\"+02:00\"},");
b.append("{\"n\":\"15\",\"sv\":\"U\"}]}");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*******************************************************************************
* Copyright (c) 2024 Sierra Wireless and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.html.
*
* Contributors:
* Sierra Wireless - initial API and implementation
*******************************************************************************/
package org.eclipse.leshan.core.node.codec;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.params.provider.Arguments.arguments;

import java.time.Instant;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import org.eclipse.leshan.core.model.LwM2mModel;
import org.eclipse.leshan.core.model.StaticModel;
import org.eclipse.leshan.core.node.LwM2mPath;
import org.eclipse.leshan.core.node.LwM2mSingleResource;
import org.eclipse.leshan.core.node.TimestampedLwM2mNode;
import org.eclipse.leshan.core.request.ContentFormat;
import org.eclipse.leshan.core.util.TestObjectLoader;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

public class LwM2mNodeDecoderEncoderTest {

private final LwM2mDecoder decoder = new DefaultLwM2mDecoder();
private final LwM2mEncoder encoder = new DefaultLwM2mEncoder();
private final LwM2mModel model = new StaticModel(TestObjectLoader.loadAllDefault());

static Stream<org.junit.jupiter.params.provider.Arguments> contentFormats() {
return Stream.of(//
arguments(ContentFormat.JSON), //
arguments(ContentFormat.SENML_JSON), //
arguments(ContentFormat.SENML_CBOR));
}

@ParameterizedTest(name = "{0}")
@MethodSource("contentFormats")
public void encode_decode_timestamped_value(ContentFormat format) {

// resource used for test
LwM2mPath resourcePath = new LwM2mPath("3442/0/120");
Instant t1 = Instant.parse("2024-05-23T21:55:00.556635828Z");
LwM2mSingleResource resource = LwM2mSingleResource.newIntegerResource(resourcePath.getResourceId(), 3600);
List<TimestampedLwM2mNode> timestampedData = Arrays.asList(new TimestampedLwM2mNode(t1, resource));

// try to encode then to decode and compare result
byte[] encodedTimestampedData = encoder.encodeTimestampedData(timestampedData, format, resourcePath, model);

List<TimestampedLwM2mNode> decodeTimestampedData = decoder.decodeTimestampedData(encodedTimestampedData, format,
resourcePath, model);

assertEquals(timestampedData, decodeTimestampedData);
}

}

0 comments on commit d876b69

Please sign in to comment.