Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Duplicate key check in JacksonJrsTreeCodec #127

Merged
merged 14 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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