Skip to content

Commit

Permalink
use gson v2.12.0, parse json strictly (#70)
Browse files Browse the repository at this point in the history
* update gson; parse json strictly;

* update gson version in ant and workflows

* keep compatibility w/ old gsons for now

* call JsonReader::setStrictness reflectively

* minor refactor

* recover from InvocationTargetException, LinkageError;

cache Method and Enum;

* minor refactor

* catch IllegalArgumentException

* declare version range for gson dependency

* simplify strictness fallback

* update gson version

* update gson resolution

* simplify gradle build, fix gradle < v5.0

* add performance note to readme; minor refactor;

* update workflow

* set up version constraints;

reduce minimum gradle version to 4.6;

* improve gson version resolution;

raise minumum gradle version to 5.0;

* update workflow

* improve note on JSON parsing

* add comments
  • Loading branch information
esaulpaugh authored Feb 3, 2025
1 parent 5e9c464 commit 4f1fcec
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 36 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/arm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
uses: actions/setup-java@v4
with:
distribution: ${{ matrix.distribution }}
java-version: '8.0.432'
java-version: '8.0.442'
java-package: jdk
cache: 'gradle'

Expand All @@ -30,4 +30,4 @@ jobs:
java -version
chmod +x ./gradlew
./gradlew build --no-daemon
ant -noinput -buildfile build.xml -Drepository="/.gradle/caches/modules-2/files-2.1" -Dgson_path="/com.google.code.gson/gson/2.10.1/b3add478d4382b78ea20b1671390a858002feb6c" clean all build-jar
ant -noinput -buildfile build.xml -Drepository="/.gradle/caches/modules-2/files-2.1" -Dgson_path="/com.google.code.gson/gson/2.12.0/10596b68aaca6230f7c40bfd9298b21ff4b84103" clean all build-jar
4 changes: 2 additions & 2 deletions .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ jobs:
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4
with:
gradle-version: 4.10.3
gradle-version: 5.6.4

- name: Run gradle and ant builds
run: |
java -version
gradle -version
gradle build --no-daemon
ant -noinput -buildfile build.xml -Drepository="/.gradle/caches/modules-2/files-2.1" -Dgson_path="/com.google.code.gson/gson/2.10.1/b3add478d4382b78ea20b1671390a858002feb6c" clean all build-jar
ant -noinput -buildfile build.xml -Drepository="/.gradle/caches/modules-2/files-2.1" -Dgson_path="/com.google.code.gson/gson/2.12.0/10596b68aaca6230f7c40bfd9298b21ff4b84103" clean all build-jar
2 changes: 1 addition & 1 deletion .github/workflows/x86.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ jobs:
java -version
chmod +x ./gradlew
./gradlew build --no-daemon
ant -noinput -buildfile build.xml -Drepository="/.gradle/caches/modules-2/files-2.1" -Dgson_path="/com.google.code.gson/gson/2.10.1/b3add478d4382b78ea20b1671390a858002feb6c" clean all build-jar
ant -noinput -buildfile build.xml -Drepository="/.gradle/caches/modules-2/files-2.1" -Dgson_path="/com.google.code.gson/gson/2.12.0/10596b68aaca6230f7c40bfd9298b21ff4b84103" clean all build-jar
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,9 @@ Also includes optimized implementations of:
* Keccak
* hexadecimal

headlong depends on gson v2.10.1 for the abi package. Test suite should take less than one minute to run. Test packages require junit. Jar size is ~128 KiB. Java 8+.
headlong depends on gson v2.1 or greater at runtime and v2.11.0 or greater at compile time. Test suite should take less than one minute to run. Test packages require junit. Jar size is ~128 KiB. Java 8+.

For best JSON parsing performance, make sure objects are compact and that the "type" field is positioned first. See ABIJSON.tryParseStreaming. This can be done via the method `Function#toJson(boolean)` while giving `false` as the argument (no pretty print).

See the wiki for more, such as packed encoding (and decoding) and RLP Object Notation: https://github.com/esaulpaugh/headlong/wiki

Expand Down
18 changes: 17 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,28 @@ repositories {
mavenCentral()
}

final String gsonVersion = "2.12.0"
final String junitVersion = "5.11.4"
final String jmhVersion = "1.37"
final String bcVersion = "1.80"

final String requires = "[2.1, " + gsonVersion + "]" // cap the require at the preferred version
final String runtimeRange = "[2.1,)" // allow later versions at runtime

dependencies {
implementation("com.google.code.gson:gson:2.10.1")
implementation("com.google.code.gson:gson:" + gsonVersion) {
version {
require(requires) // published in "dependencies"
}
exclude(group: "com.google.errorprone", module: "error_prone_annotations")
}
constraints {
implementation("com.google.code.gson:gson:") {
version {
require(runtimeRange) // published in "dependencyConstraints" / "<dependencyManagement>"
}
}
}

testImplementation("org.junit.jupiter:junit-jupiter-api:" + junitVersion)
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:" + junitVersion)
Expand Down
15 changes: 14 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,24 @@
// mavenCentral()
//}
//
//val gsonVersion = "2.12.0"
//val junitVersion = "5.11.4"
//val bcVersion = "1.80"
//
//dependencies {
// implementation("com.google.code.gson:gson:2.10.1")
// implementation("com.google.code.gson:gson:$gsonVersion") {
// version {
// strictly(gsonVersion)
// }
// exclude(group = "com.google.errorprone", module = "error_prone_annotations")
// }
// constraints {
// implementation("com.google.code.gson:gson") {
// version {
// require("[2.1,)")
// }
// }
// }
//
// testImplementation("org.junit.jupiter:junit-jupiter-api:$junitVersion")
// testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$junitVersion")
Expand Down
12 changes: 6 additions & 6 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@

<!-- Project Libraries -->

<path id="lib.mvn:_com.google.code.gson:gson:2.10.1.classpath">
<pathelement location="${user.home}${repository}${gson_path}/gson-2.10.1.jar"/>
<path id="lib.mvn:_com.google.code.gson:gson:2.12.0.classpath">
<pathelement location="${user.home}${repository}${gson_path}/gson-2.12.0.jar"/>
</path>

<!-- Modules -->
Expand Down Expand Up @@ -129,22 +129,22 @@
</path>

<path id="headlong.main.module.production.classpath">
<path refid="lib.mvn:_com.google.code.gson:gson:2.10.1.classpath"/>
<path refid="lib.mvn:_com.google.code.gson:gson:2.12.0.classpath"/>
</path>

<path id="headlong.main.runtime.production.module.classpath">
<pathelement location="${headlong.main.output.dir}"/>
<path refid="lib.mvn:_com.google.code.gson:gson:2.10.1.classpath"/>
<path refid="lib.mvn:_com.google.code.gson:gson:2.12.0.classpath"/>
</path>

<path id="headlong.main.module.classpath">
<pathelement location="${headlong.main.output.dir}"/>
<path refid="lib.mvn:_com.google.code.gson:gson:2.10.1.classpath"/>
<path refid="lib.mvn:_com.google.code.gson:gson:2.12.0.classpath"/>
</path>

<path id="headlong.main.runtime.module.classpath">
<pathelement location="${headlong.main.output.dir}"/>
<path refid="lib.mvn:_com.google.code.gson:gson:2.10.1.classpath"/>
<path refid="lib.mvn:_com.google.code.gson:gson:2.12.0.classpath"/>
</path>


Expand Down
22 changes: 22 additions & 0 deletions graal-config/reflect-config.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,26 @@
[
{
"name": "com.google.gson.stream.JsonReader",
"methods": [
{
"name": "setStrictness",
"parameterTypes": ["com.google.gson.Strictness"]
}
]
},
{
"name": "com.google.gson.Strictness",
"methods": [
{
"name": "valueOf",
"parameterTypes": ["java.lang.String"]
},
{
"name": "valueOf",
"parameterTypes": [ "java.lang.Class" ,"java.lang.String"]
}
]
},
{
"name" : "byte[]",
"unsafeAllocated" : true
Expand Down
19 changes: 8 additions & 11 deletions gradle/verification-metadata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,17 @@
</trusted-keys>
</configuration>
<components>
<component group="com.google.code.gson" name="gson-parent" version="2.10.1">
<artifact name="gson-parent-2.10.1.pom">
<sha256 value="4248e0882426c615182385d6086c3ef3262e769957189e29306280b85482b833" origin="repo.maven.apache.org/maven2/"/>
<component group="com.google.code.gson" name="gson-parent" version="2.12.0">
<artifact name="gson-parent-2.12.0.pom">
<sha256 value="b6dd0454a689944b4a66641c90792b59888ad24f43be69bcf6b165e2e29ce010" origin="repo.maven.apache.org/maven2/"/>
</artifact>
</component>
<component group="com.google.code.gson" name="gson" version="2.10.1">
<artifact name="gson-2.10.1.jar">
<sha256 value="4241c14a7727c34feea6507ec801318a3d4a90f070e4525681079fb94ee4c593" origin="repo.maven.apache.org/maven2/"/>
<component group="com.google.code.gson" name="gson" version="2.12.0">
<artifact name="gson-2.12.0.jar">
<sha256 value="4d377f51c84bb5b4e5603bdee5fe7ffc9ab6b7aee4ee0e1f62c6fadd84c5fa05" origin="repo.maven.apache.org/maven2/"/>
</artifact>
<artifact name="gson-2.10.1.pom">
<sha256 value="d2b115634f5c085db4b9c9ffc2658e89e231fdbfbe2242121a1cd95d4d948dd7" origin="repo.maven.apache.org/maven2/"/>
</artifact>
<artifact name="gson-2.10.1-sources.jar">
<sha256 value="eee1cc5c1f4267ee194cc245777e68084738ef390acd763354ce0ff6bfb7bcc1" origin="repo.maven.apache.org/maven2/"/>
<artifact name="gson-2.12.0.pom">
<sha256 value="ee4cb3d1d489b7ceb8bc73805e024cd36a12d19816585c8b0d46cfd8b604ea46" origin="repo.maven.apache.org/maven2/"/>
</artifact>
</component>

Expand Down
2 changes: 1 addition & 1 deletion headlong.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
repository=/.m2/repository
gson_path=/com/google/code/gson/gson/2.10.1
gson_path=/com/google/code/gson/gson/2.12.0
project.name=headlong
project.version=12.3.4-SNAPSHOT
8 changes: 7 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,15 @@
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
<version>2.12.0</version>
<scope>provided</scope>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotations</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
Expand Down
41 changes: 32 additions & 9 deletions src/main/java/com/esaulpaugh/headlong/abi/ABIJSON.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.google.gson.JsonElement;
import com.google.gson.JsonIOException;
import com.google.gson.JsonObject;
import com.google.gson.Strictness;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
Expand All @@ -29,6 +30,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
Expand Down Expand Up @@ -119,7 +121,7 @@ public static <T extends ABIObject> List<T> parseElements(String arrayJson, Set<
}

public static <T extends ABIObject> List<T> parseElements(int flags, String arrayJson, Set<TypeEnum> types) {
try (final JsonReader reader = read(arrayJson)) {
try (final JsonReader reader = reader(arrayJson)) {
return parseArray(reader, types, flags);
} catch (IOException io) {
throw new IllegalStateException(io);
Expand All @@ -143,7 +145,7 @@ public static <T extends ABIObject> Iterator<T> iterator(int flags, String array
}

public static <T extends ABIObject> List<T> parseABIField(int flags, String objectJson, Set<TypeEnum> types) {
try (final JsonReader reader = read(objectJson)) {
try (final JsonReader reader = reader(objectJson)) {
reader.beginObject();
while (reader.peek() != JsonToken.END_OBJECT) {
if ("abi".equals(reader.nextName())) {
Expand Down Expand Up @@ -285,7 +287,7 @@ static class JsonSpliterator<T extends ABIObject> extends Spliterators.AbstractS
JsonSpliterator(String arrayJson, Set<TypeEnum> types, int flags) {
super(Long.SIZE, ORDERED | NONNULL | IMMUTABLE);
try {
JsonReader reader = read(arrayJson);
JsonReader reader = reader(arrayJson);
reader.beginArray();
this.jsonReader = reader;
this.types = types;
Expand Down Expand Up @@ -341,12 +343,12 @@ private void doClose() throws IOException {
}

static <T extends ABIObject> T parseABIObject(String json, Set<TypeEnum> types, MessageDigest digest, int flags) {
return parseABIObject(read(json), types, digest, flags);
return parseABIObject(reader(json), types, digest, flags);
}

/** Reads an {@link ABIObject} from JSON and closes the {@link InputStream}. Assumes UTF-8 encoding. */
static <T extends ABIObject> T parseABIObject(InputStream is, Set<TypeEnum> types, MessageDigest digest, int flags) {
return parseABIObject(new JsonReader(new InputStreamReader(is, StandardCharsets.UTF_8)), types, digest, flags);
return parseABIObject(reader(is), types, digest, flags);
}

private static <T extends ABIObject> T parseABIObject(JsonReader reader, Set<TypeEnum> types, MessageDigest digest, int flags) {
Expand Down Expand Up @@ -388,7 +390,7 @@ static <T extends ABIObject> T tryParseStreaming(JsonReader reader, Set<TypeEnum
}
}
reader.endObject();
JsonReader r = read(jsonObject.toString());
JsonReader r = reader(jsonObject.toString());
r.beginObject();
return finishParse(t, r, digest, flags);
}
Expand Down Expand Up @@ -459,7 +461,7 @@ private static ContractError<?> parseError(JsonReader reader, int flags) throws
return new ContractError<>(name, tt);
}

private static TupleType<?> parseTupleType(JsonReader reader, final boolean eventParams, final int flags) throws IOException {
private static TupleType<?> parseTupleType(final JsonReader reader, final boolean eventParams, final int flags) throws IOException {
if (reader.peek() == JsonToken.NULL) {
reader.nextNull();
return TupleType.empty(flags);
Expand Down Expand Up @@ -542,8 +544,29 @@ private static TupleType<?> parseTupleType(JsonReader reader, final boolean even
}
}

private static JsonReader read(String json) {
return new JsonReader(new StringReader(json));
private static JsonReader reader(String json) {
return strict(new StringReader(json));
}

private static JsonReader reader(InputStream input) {
return strict(new InputStreamReader(input, StandardCharsets.UTF_8));
}

private static volatile boolean fallback = false;

@SuppressWarnings("deprecation")
private static JsonReader strict(Reader reader) {
final JsonReader jsonReader = new JsonReader(reader);
if (!fallback) {
try {
jsonReader.setStrictness(Strictness.STRICT);
return jsonReader;
} catch (LinkageError le) { // e.g. at runtime, gson is below 2.11.0
fallback = true;
}
}
jsonReader.setLenient(false);
return jsonReader;
}

private static <T extends ABIObject> List<T> parseArray(final JsonReader reader, Set<TypeEnum> types, int flags) throws IOException {
Expand Down

0 comments on commit 4f1fcec

Please sign in to comment.