Skip to content

Commit f574128

Browse files
committed
Fix JSON node sorting
Fixes an issue where we may compare two JSON objects and get different results based on which direction the compare is made. This was caused by having a different list of properties for the compare if the two JSON nodes had different lists of properties.
1 parent 129396f commit f574128

File tree

3 files changed

+7071
-1
lines changed

3 files changed

+7071
-1
lines changed

src/main/java/org/spdx/jacksonstore/JacksonSerializer.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,11 @@ private int compareObject(JsonNode arg0, JsonNode arg1) {
161161
}
162162
List<String> fieldNames = new ArrayList<>();
163163
arg0.fieldNames().forEachRemaining(fieldNames::add);
164+
arg1.fieldNames().forEachRemaining(field -> {
165+
if (!fieldNames.contains(field)) {
166+
fieldNames.add(field);
167+
}
168+
});
164169
Collections.sort(fieldNames);
165170
int retval = 0;
166171
for (String fieldName:fieldNames) {
@@ -335,7 +340,7 @@ public ObjectNode docToJsonNode(String documentUri) throws InvalidSPDXAnalysisEx
335340
* Sorts the elements of an ArrayNode in place
336341
* @param an ArrayNode to sort
337342
*/
338-
private void sortArrayNode(ArrayNode an) {
343+
protected static void sortArrayNode(ArrayNode an) {
339344
List<JsonNode> arrayElements = StreamSupport.stream(an.spliterator(), false).sorted(NODE_COMPARATOR).collect(Collectors.toList());
340345
an.removeAll();
341346
an.addAll(arrayElements);

src/test/java/org/spdx/jacksonstore/MultiFormatStoreTest.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.util.Optional;
3838
import java.util.stream.Collectors;
3939

40+
import com.fasterxml.jackson.databind.node.ArrayNode;
4041
import org.spdx.core.DefaultModelStore;
4142
import org.spdx.core.InvalidSPDXAnalysisException;
4243
import org.spdx.core.ModelRegistry;
@@ -93,6 +94,7 @@ public class MultiFormatStoreTest extends TestCase {
9394
static final String XML_1REL_FILE_PATH = "testResources" + File.separator + "SPDXXML-SingleRel-v2.3.spdx.xml";
9495
static final String JSON_SCHEMA_V2_3 = "testResources" + File.separator + "spdx-schema.json";
9596
static final String UNSORTED_JSON = "testResources" + File.separator + "SPDXJSONUnsortedIds.json";
97+
static final String UNSORTED_RELATIONSHIPS = "testResources" + File.separator + "unsortedrelationships.json";
9698

9799
/* (non-Javadoc)
98100
* @see junit.framework.TestCase#setUp()
@@ -758,4 +760,38 @@ public void testSortOrder() throws InvalidSPDXAnalysisException, IOException, Sp
758760
tempDirPath.toFile().delete();
759761
}
760762
}
763+
764+
public void testRegressionSort() throws IOException {
765+
File jsonFile = new File(UNSORTED_RELATIONSHIPS);
766+
ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
767+
JsonNode relationships = null;
768+
try (FileInputStream stream = new FileInputStream(jsonFile)) {
769+
relationships = mapper.readTree(stream);
770+
}
771+
assertTrue(relationships.isArray());
772+
ArrayNode relArray = (ArrayNode)relationships;
773+
for (int i = 0; i < relArray.size(); i++) {
774+
for (int j = i; j < relArray.size(); j++) {
775+
JsonNode rel1 = relArray.get(i);
776+
JsonNode rel2 = relArray.get(j);
777+
int result = JacksonSerializer.NODE_COMPARATOR.compare(rel1, rel2);
778+
int revers = JacksonSerializer.NODE_COMPARATOR.compare(rel2, rel1);
779+
if (relArray.get(i).equals(relArray.get(j))) {
780+
assertEquals(0, result);
781+
}
782+
if (relArray.get(j).equals(relArray.get(i))) {
783+
assertEquals(0, result);
784+
}
785+
if (result < 0) {
786+
assertTrue(revers > 0);
787+
} else if (result > 0) {
788+
assertTrue(revers < 0);
789+
} else {
790+
assertEquals(0, revers);
791+
}
792+
}
793+
}
794+
JacksonSerializer.sortArrayNode(relArray);
795+
}
796+
761797
}

0 commit comments

Comments
 (0)