Skip to content

Commit

Permalink
Adding Duplicate key check in JacksonJrsTreeCodec (#127)
Browse files Browse the repository at this point in the history
  • Loading branch information
Shounaks authored Mar 11, 2024
1 parent 041d26a commit cec7bac
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.*;

import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.jr.ob.JSONObjectException;

/**
* {@link TreeCodec} implementation that can build "simple", immutable
Expand All @@ -13,9 +14,6 @@
public class JacksonJrsTreeCodec extends TreeCodec
{
public static JrsMissing MISSING = JrsMissing.instance;

public static final JacksonJrsTreeCodec SINGLETON = new JacksonJrsTreeCodec();

protected final ObjectCodec _objectCodec;

// @since 2.17
Expand Down Expand Up @@ -44,7 +42,7 @@ private JrsValue nodeFrom(JsonParser p) throws IOException
{
int tokenId = p.hasCurrentToken()
? p.currentTokenId() : p.nextToken().id();

switch (tokenId) {
case JsonTokenId.ID_TRUE:
return JrsBoolean.TRUE;
Expand All @@ -55,24 +53,25 @@ private JrsValue nodeFrom(JsonParser p) throws IOException
return new JrsNumber(p.getNumberValue());
case JsonTokenId.ID_STRING:
return new JrsString(p.getText());
case JsonTokenId.ID_START_ARRAY:
{
List<JrsValue> values = _list();
while (p.nextToken() != JsonToken.END_ARRAY) {
values.add(nodeFrom(p));
}
return new JrsArray(values);
case JsonTokenId.ID_START_ARRAY: {
List<JrsValue> values = _list();
while (p.nextToken() != JsonToken.END_ARRAY) {
values.add(nodeFrom(p));
}
case JsonTokenId.ID_START_OBJECT:
{
Map<String, JrsValue> values = _map();
while (p.nextToken() != JsonToken.END_OBJECT) {
final String currentName = p.currentName();
p.nextToken();
values.put(currentName, nodeFrom(p));
return new JrsArray(values);
}
case JsonTokenId.ID_START_OBJECT: {
Map<String, JrsValue> values = _map();
while (p.nextToken() != JsonToken.END_OBJECT) {
final String currentName = p.currentName();
p.nextToken();
JrsValue prev = values.put(currentName, nodeFrom(p));
if (_failOnDuplicateKeys && (prev != null)) {
throw new JSONObjectException("Duplicate key (key '" + currentName + "')");
}
return new JrsObject(values);
}
return new JrsObject(values);
}
case JsonTokenId.ID_EMBEDDED_OBJECT:
// 07-Jan-2016, tatu: won't happen with JSON, but other types like Smile
// may produce binary data or such
Expand All @@ -82,7 +81,7 @@ private JrsValue nodeFrom(JsonParser p) throws IOException
return JrsNull.instance;
default:
}
throw new UnsupportedOperationException("Unsupported token id "+tokenId+" ("+p.currentToken()+")");
throw new UnsupportedOperationException("Unsupported token id " + tokenId + " (" + p.currentToken() + ")");
}

@Override
Expand Down Expand Up @@ -134,7 +133,7 @@ public JsonParser treeAsTokens(TreeNode node) {
* @since 2.8
*/
public JrsBoolean booleanNode(boolean state) {
return state? JrsBoolean.TRUE : JrsBoolean.FALSE;
return state ? JrsBoolean.TRUE : JrsBoolean.FALSE;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.fasterxml.jackson.jr.stree;

import com.fasterxml.jackson.jr.ob.JSON;
import com.fasterxml.jackson.jr.ob.JSONObjectException;

/**
* Tests for reading content using {@link JSON} with proper
* codec registration
*/
public class DupFieldNameInTree51Test extends JacksonJrTreeTestBase
{
private final JSON NO_DUPS_JSON = JSON.builder()
.enable(JSON.Feature.FAIL_ON_DUPLICATE_MAP_KEYS)
.register(new JrSimpleTreeExtension())
.build();

private final JSON DUPS_OK_JSON = JSON.builder()
.disable(JSON.Feature.FAIL_ON_DUPLICATE_MAP_KEYS)
.register(new JrSimpleTreeExtension())
.build();

// [jackson-jr#51]: test dup keys for trees too
public void testFailOnDupMapKeys() throws Exception
{
assertTrue(NO_DUPS_JSON.isEnabled(JSON.Feature.FAIL_ON_DUPLICATE_MAP_KEYS));
final String json = "{\"a\":1,\"b\":2,\"b\":3,\"c\":4}";
try {
/*TreeNode node =*/ NO_DUPS_JSON.treeFrom(json);
fail("Should not pass");
} catch (JSONObjectException e) {
verifyException(e, "Duplicate key");
}

assertFalse(DUPS_OK_JSON.isEnabled(JSON.Feature.FAIL_ON_DUPLICATE_MAP_KEYS));
// But should pass fine without setting
assertNotNull(DUPS_OK_JSON.treeFrom(json));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ protected JSON jsonWithTreeCodec() {
// 13-Feb-2020, tatu: There are 2 different ways actually..
// .treeCodec(new JacksonJrsTreeCodec())
.register(new JrSimpleTreeExtension())
.build();
.build();
}
}

This file was deleted.

2 changes: 2 additions & 0 deletions release-notes/CREDITS-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ Julian Honnen (@jhonnen)
(2.17.0)
* Contributed PoC of #25: Add support single-int Constructors
(2.17.0)
* Contributed #51: Duplicate key detection does not work for (simple) Trees
(2.17.0)
* Contributed fix for #93: Skip serialization of `groovy.lang.MetaClass` values
to avoid `StackOverflowError`
(2.17.0)
Expand Down
2 changes: 2 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Not yet released

#7: Support deserialization of `int[]`
(contributed by @Shounaks)
#51: Duplicate key detection does not work for (simple) Trees
(contributed by @Shounaks)
#131: Add mechanism for `JacksonJrExtension`s to access state of `JSON.Feature`s

2.17.0-rc1 (26-Feb-2024)
Expand Down

0 comments on commit cec7bac

Please sign in to comment.