Skip to content

Commit

Permalink
Adding Implementation + Groovy and Java Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Shounaks committed Mar 7, 2024
1 parent 68f23bf commit 6e08b93
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,13 @@ public enum Feature
*/
USE_IS_GETTERS(true, true),

/**
* Feature that provides support for Groovy & JDK14 records, by allowing
* reading of "non-get-getters" in a class, (like for a field named <code>amount</code>
* the getter would be <code>amount()</code>)
* */
USE_FIELD_NAME_GETTERS(true,true),

/**
* Feature that enables use of public fields instead of setters and getters,
* in cases where no setter/getter is available.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Map;
import java.util.TreeMap;

import com.fasterxml.jackson.jr.ob.JSON;
import com.fasterxml.jackson.jr.ob.impl.POJODefinition.Prop;
import com.fasterxml.jackson.jr.ob.impl.POJODefinition.PropBuilder;


import static com.fasterxml.jackson.jr.ob.JSON.Feature.INCLUDE_STATIC_FIELDS;
import static com.fasterxml.jackson.jr.ob.JSON.Feature.USE_FIELD_NAME_GETTERS;

/**
* Helper class that jackson-jr uses by default to introspect POJO properties
* (represented as {@link POJODefinition}) to build general POJO readers
Expand Down Expand Up @@ -97,7 +101,9 @@ private static void _introspect(Class<?> currType, Map<String, PropBuilder> prop
// First, check base type
_introspect(currType.getSuperclass(), props, features);

final boolean noStatics = JSON.Feature.INCLUDE_STATIC_FIELDS.isDisabled(features);
final boolean noStatics = INCLUDE_STATIC_FIELDS.isDisabled(features);
final boolean isFieldNameGettersEnabled = USE_FIELD_NAME_GETTERS.isEnabled(features);

// then public fields (since 2.8); may or may not be ultimately included
// but at this point still possible
for (Field f : currType.getDeclaredFields()) {
Expand Down Expand Up @@ -146,6 +152,17 @@ private static void _introspect(Class<?> currType, Map<String, PropBuilder> prop
_propFrom(props, name).withIsGetter(m);
}
}
else if (isFieldNameGettersEnabled) {
// This will allow getters with field name as their getters, like the ones generated by Groovy
// If method name matches with field name, & method return type matches with field type
// only then it can be considered a direct name getter.
final String decapName = name;
Arrays.stream(currType.getDeclaredFields())
.filter(f -> f.getName().equals(m.getName()))
.filter(f -> Modifier.isPublic(m.getModifiers()) && m.getReturnType().equals(f.getType()))
.findFirst()
.ifPresent(f -> _propFrom(props, decap(decapName)).withGetter(m));
}
} else if (argTypes.length == 1) { // setter?
// Non-public setters are fine if we can force access, don't yet check
// let's also not bother about return type; setters that return value are fine
Expand Down
5 changes: 5 additions & 0 deletions jr-test-module/src/test/groovy/GroovyObjectSupportTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import com.fasterxml.jackson.jr.ob.JSON
import org.junit.Assert
import org.junit.Test

/**
* A minor note on running/debugging this test on local, if you are using intellij, please
* change `<packaging>pom</packaging>` to `<packaging>bundle</packaging>`. this is causing
* some issue with the IDE.
*/
class GroovyObjectSupportTest {
@Test
void testSimpleGroovyObject() throws Exception {
Expand Down
59 changes: 59 additions & 0 deletions jr-test-module/src/test/groovy/GroovyRecordsTest.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import com.fasterxml.jackson.jr.ob.JSON
import org.junit.Assert
import org.junit.Test

/**
* A minor note on running/debugging this test on local, if you are using intellij, please
* change `<packaging>pom</packaging>` to `<packaging>bundle</packaging>`. this is causing
* some issue with the IDE.
*/
class GroovyRecordsTest {

@Test
void testRecord() throws Exception {
def json = JSON.std.asString(new Cow("foo", Map<String, String>.of("foo", "bar")))
def expected = """{"message":"foo","object":{"foo":"bar"}}"""
Assert.assertEquals(expected, json)
}

@Test
void testRecordEquivalentObjects() throws Exception {
def expected = """{"message":"foo","object":{"foo":"bar"}}"""

def json = JSON.std.asString(new SimpleGroovyObject("foo", Map<String, String>.of("foo", "bar")))
Assert.assertEquals(expected, json)

def json2 = JSON.std.asString(new GroovyObjectWithNamedGetters("foo", Map<String, String>.of("foo", "bar")))
Assert.assertEquals(expected, json2)
}
}

class SimpleGroovyObject {
public final String message
public final Map<String, String> object

SimpleGroovyObject(String message, Map<String, String> object) {
this.message = message
this.object = object
}
}

class GroovyObjectWithNamedGetters {
private final String message
private final Map<String, String> object

GroovyObjectWithNamedGetters(String message, Map<String, String> object) {
this.message = message
this.object = object
}

String message() {
return message
}

Map<String, String> object() {
return object
}
}

record Cow(String message, Map<String, String> object) {}
22 changes: 22 additions & 0 deletions jr-test-module/src/test/java/Java14RecordTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import com.fasterxml.jackson.jr.ob.JSON;
import org.junit.Assert;
import org.junit.Test;

import java.io.IOException;
import java.util.Map;

/**
* This test is in test module since the JDK version to be tested is higher than other, and hence supports Records.
*/
public class Java14RecordTest {

@Test
public void testJava14RecordSupport() throws IOException {
var expectedString = "{\"message\":\"MOO\",\"object\":{\"Foo\":\"Bar\"}}";
var json = JSON.std.asString(new Cow("MOO", Map.of("Foo", "Bar")));
Assert.assertEquals(expectedString, json);
}

record Cow(String message, Map<String, String> object) {
}
}

0 comments on commit 6e08b93

Please sign in to comment.