diff --git a/core/src/main/java/org/apache/iceberg/MetadataUpdateParser.java b/core/src/main/java/org/apache/iceberg/MetadataUpdateParser.java index 8b3cb41edb81..4279502c8021 100644 --- a/core/src/main/java/org/apache/iceberg/MetadataUpdateParser.java +++ b/core/src/main/java/org/apache/iceberg/MetadataUpdateParser.java @@ -216,7 +216,7 @@ public static void toJson(MetadataUpdate metadataUpdate, JsonGenerator generator */ public static MetadataUpdate fromJson(String json) { try { - return fromJson(JsonUtil.mapper().readValue(json, JsonNode.class)); + return fromJson(JsonUtil.parseJson(json)); } catch (IOException e) { throw new UncheckedIOException("Failed to read JSON string: " + json, e); } diff --git a/core/src/main/java/org/apache/iceberg/PartitionSpecParser.java b/core/src/main/java/org/apache/iceberg/PartitionSpecParser.java index 67ec98b763de..e3c6ebbc0a7f 100644 --- a/core/src/main/java/org/apache/iceberg/PartitionSpecParser.java +++ b/core/src/main/java/org/apache/iceberg/PartitionSpecParser.java @@ -104,7 +104,7 @@ public static PartitionSpec fromJson(Schema schema, String json) { return SPEC_CACHE.get(Pair.of(schema.asStruct(), json), schemaJsonPair -> { try { - return fromJson(schema, JsonUtil.mapper().readValue(json, JsonNode.class)); + return fromJson(schema, JsonUtil.parseJson(json)); } catch (IOException e) { throw new RuntimeIOException(e); } @@ -149,7 +149,7 @@ static PartitionSpec fromJsonFields(Schema schema, int specId, JsonNode json) { static PartitionSpec fromJsonFields(Schema schema, int specId, String json) { try { - return fromJsonFields(schema, specId, JsonUtil.mapper().readValue(json, JsonNode.class)); + return fromJsonFields(schema, specId, JsonUtil.parseJson(json)); } catch (IOException e) { throw new RuntimeIOException(e, "Failed to parse partition spec fields: %s", json); } diff --git a/core/src/main/java/org/apache/iceberg/SchemaParser.java b/core/src/main/java/org/apache/iceberg/SchemaParser.java index 0a4f6f389868..65e7222632ae 100644 --- a/core/src/main/java/org/apache/iceberg/SchemaParser.java +++ b/core/src/main/java/org/apache/iceberg/SchemaParser.java @@ -274,7 +274,7 @@ public static Schema fromJson(JsonNode json) { public static Schema fromJson(String json) { return SCHEMA_CACHE.get(json, jsonKey -> { try { - return fromJson(JsonUtil.mapper().readValue(jsonKey, JsonNode.class)); + return fromJson(JsonUtil.parseJson(json)); } catch (IOException e) { throw new RuntimeIOException(e); } diff --git a/core/src/main/java/org/apache/iceberg/SnapshotParser.java b/core/src/main/java/org/apache/iceberg/SnapshotParser.java index e4a4428b49af..464f775c3a7b 100644 --- a/core/src/main/java/org/apache/iceberg/SnapshotParser.java +++ b/core/src/main/java/org/apache/iceberg/SnapshotParser.java @@ -171,7 +171,7 @@ static Snapshot fromJson(FileIO io, JsonNode node) { public static Snapshot fromJson(FileIO io, String json) { try { - return fromJson(io, JsonUtil.mapper().readValue(json, JsonNode.class)); + return fromJson(io, JsonUtil.parseJson(json)); } catch (IOException e) { throw new RuntimeIOException(e, "Failed to read version from json: %s", json); } diff --git a/core/src/main/java/org/apache/iceberg/SnapshotRefParser.java b/core/src/main/java/org/apache/iceberg/SnapshotRefParser.java index c57f251dd46f..7514404e6de0 100644 --- a/core/src/main/java/org/apache/iceberg/SnapshotRefParser.java +++ b/core/src/main/java/org/apache/iceberg/SnapshotRefParser.java @@ -74,7 +74,7 @@ public static SnapshotRef fromJson(String json) { Preconditions.checkArgument(json != null && !json.isEmpty(), "Cannot parse snapshot ref from invalid JSON: %s", json); try { - return fromJson(JsonUtil.mapper().readValue(json, JsonNode.class)); + return fromJson(JsonUtil.parseJson(json)); } catch (IOException e) { throw new UncheckedIOException("Failed to parse snapshot ref: " + json, e); } diff --git a/core/src/main/java/org/apache/iceberg/SortOrderParser.java b/core/src/main/java/org/apache/iceberg/SortOrderParser.java index 002c859d8222..fa37e31f5465 100644 --- a/core/src/main/java/org/apache/iceberg/SortOrderParser.java +++ b/core/src/main/java/org/apache/iceberg/SortOrderParser.java @@ -143,7 +143,7 @@ public static SortOrder fromJson(Schema schema, JsonNode json) { public static UnboundSortOrder fromJson(String json) { try { - return fromJson(JsonUtil.mapper().readValue(json, JsonNode.class)); + return fromJson(JsonUtil.parseJson(json)); } catch (IOException e) { throw new UncheckedIOException(e); } diff --git a/core/src/main/java/org/apache/iceberg/TableMetadataParser.java b/core/src/main/java/org/apache/iceberg/TableMetadataParser.java index c167b08706a1..6cd211da7391 100644 --- a/core/src/main/java/org/apache/iceberg/TableMetadataParser.java +++ b/core/src/main/java/org/apache/iceberg/TableMetadataParser.java @@ -261,7 +261,7 @@ public static TableMetadata read(FileIO io, String path) { public static TableMetadata read(FileIO io, InputFile file) { Codec codec = Codec.fromFileName(file.location()); try (InputStream is = codec == Codec.GZIP ? new GZIPInputStream(file.newStream()) : file.newStream()) { - return fromJson(io, file, JsonUtil.mapper().readValue(is, JsonNode.class)); + return fromJson(io, file, JsonUtil.parseJson(is)); } catch (IOException e) { throw new RuntimeIOException(e, "Failed to read file: %s", file); } @@ -290,7 +290,7 @@ public static TableMetadata fromJson(FileIO io, String json) { */ public static TableMetadata fromJson(FileIO io, String metadataLocation, String json) { try { - JsonNode node = JsonUtil.mapper().readValue(json, JsonNode.class); + JsonNode node = JsonUtil.parseJson(json); return fromJson(io, metadataLocation, node); } catch (IOException e) { throw new UncheckedIOException("Failed to read JSON string: " + json, e); diff --git a/core/src/main/java/org/apache/iceberg/catalog/TableIdentifierParser.java b/core/src/main/java/org/apache/iceberg/catalog/TableIdentifierParser.java index 7cc3a78066aa..d609547201be 100644 --- a/core/src/main/java/org/apache/iceberg/catalog/TableIdentifierParser.java +++ b/core/src/main/java/org/apache/iceberg/catalog/TableIdentifierParser.java @@ -83,7 +83,7 @@ public static TableIdentifier fromJson(String json) { Preconditions.checkArgument(!json.isEmpty(), "Cannot parse table identifier from invalid JSON: ''"); try { - return fromJson(JsonUtil.mapper().readValue(json, JsonNode.class)); + return fromJson(JsonUtil.parseJson(json)); } catch (IOException e) { throw new UncheckedIOException(String.format("Cannot parse table identifier from invalid JSON: %s", json), e); } diff --git a/core/src/main/java/org/apache/iceberg/mapping/NameMappingParser.java b/core/src/main/java/org/apache/iceberg/mapping/NameMappingParser.java index 5eaef84abb10..6e0280c3c13f 100644 --- a/core/src/main/java/org/apache/iceberg/mapping/NameMappingParser.java +++ b/core/src/main/java/org/apache/iceberg/mapping/NameMappingParser.java @@ -100,7 +100,7 @@ private static void toJson(MappedField field, JsonGenerator generator) throws IO public static NameMapping fromJson(String json) { try { - return fromJson(JsonUtil.mapper().readValue(json, JsonNode.class)); + return fromJson(JsonUtil.parseJson(json)); } catch (IOException e) { throw new RuntimeIOException(e, "Failed to convert version from json: %s", json); } diff --git a/core/src/main/java/org/apache/iceberg/puffin/FileMetadataParser.java b/core/src/main/java/org/apache/iceberg/puffin/FileMetadataParser.java index 59642b7ba42d..f59c35b3d670 100644 --- a/core/src/main/java/org/apache/iceberg/puffin/FileMetadataParser.java +++ b/core/src/main/java/org/apache/iceberg/puffin/FileMetadataParser.java @@ -62,7 +62,7 @@ public static String toJson(FileMetadata fileMetadata, boolean pretty) { public static FileMetadata fromJson(String json) { try { - return fromJson(JsonUtil.mapper().readValue(json, JsonNode.class)); + return fromJson(JsonUtil.parseJson(json)); } catch (IOException e) { throw new UncheckedIOException(e); } diff --git a/core/src/main/java/org/apache/iceberg/rest/auth/OAuth2Util.java b/core/src/main/java/org/apache/iceberg/rest/auth/OAuth2Util.java index 8906dcea8bb3..1ccc4cd3460d 100644 --- a/core/src/main/java/org/apache/iceberg/rest/auth/OAuth2Util.java +++ b/core/src/main/java/org/apache/iceberg/rest/auth/OAuth2Util.java @@ -248,7 +248,7 @@ public static void tokenResponseToJson(OAuthTokenResponse response, JsonGenerato public static OAuthTokenResponse tokenResponseFromJson(String json) { try { - return tokenResponseFromJson(JsonUtil.mapper().readValue(json, JsonNode.class)); + return tokenResponseFromJson(JsonUtil.parseJson(json)); } catch (IOException e) { throw new RuntimeIOException(e); } diff --git a/core/src/main/java/org/apache/iceberg/rest/requests/UpdateRequirementParser.java b/core/src/main/java/org/apache/iceberg/rest/requests/UpdateRequirementParser.java index 60029087b577..50599b7c598b 100644 --- a/core/src/main/java/org/apache/iceberg/rest/requests/UpdateRequirementParser.java +++ b/core/src/main/java/org/apache/iceberg/rest/requests/UpdateRequirementParser.java @@ -150,7 +150,7 @@ public static void toJson(UpdateRequirement updateRequirement, JsonGenerator gen */ public static UpdateRequirement fromJson(String json) { try { - return fromJson(JsonUtil.mapper().readValue(json, JsonNode.class)); + return fromJson(JsonUtil.parseJson(json)); } catch (IOException e) { throw new UncheckedIOException("Failed to read JSON string: " + json, e); } diff --git a/core/src/main/java/org/apache/iceberg/rest/responses/ErrorResponseParser.java b/core/src/main/java/org/apache/iceberg/rest/responses/ErrorResponseParser.java index da197a5b0276..86fd6a0e4d5a 100644 --- a/core/src/main/java/org/apache/iceberg/rest/responses/ErrorResponseParser.java +++ b/core/src/main/java/org/apache/iceberg/rest/responses/ErrorResponseParser.java @@ -87,7 +87,7 @@ public static void toJson(ErrorResponse errorResponse, JsonGenerator generator) */ public static ErrorResponse fromJson(String json) { try { - return fromJson(JsonUtil.mapper().readValue(json, JsonNode.class)); + return fromJson(JsonUtil.parseJson(json)); } catch (IOException e) { throw new UncheckedIOException("Failed to read JSON string: " + json, e); } diff --git a/core/src/main/java/org/apache/iceberg/util/JsonUtil.java b/core/src/main/java/org/apache/iceberg/util/JsonUtil.java index ff4a185d8aa3..6c6e5c926f7d 100644 --- a/core/src/main/java/org/apache/iceberg/util/JsonUtil.java +++ b/core/src/main/java/org/apache/iceberg/util/JsonUtil.java @@ -21,10 +21,12 @@ import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import java.io.IOException; +import java.io.InputStream; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -50,6 +52,24 @@ public static ObjectMapper mapper() { return MAPPER; } + public static JsonNode parseJson(InputStream input) throws IOException { + Preconditions.checkNotNull(input, "input is null"); + try (JsonParser parser = MAPPER.createParser(input)) { + JsonNode parsed = MAPPER.readValue(parser, JsonNode.class); + Preconditions.checkArgument(parser.nextToken() == null, "Found characters after the expected end of input"); + return parsed; + } + } + + public static JsonNode parseJson(String json) throws IOException { + Preconditions.checkNotNull(json, "input is null"); + try (JsonParser parser = MAPPER.createParser(json)) { + JsonNode parsed = MAPPER.readValue(parser, JsonNode.class); + Preconditions.checkArgument(parser.nextToken() == null, "Found characters after the expected end of input"); + return parsed; + } + } + public static int getInt(String property, JsonNode node) { Preconditions.checkArgument(node.has(property), "Cannot parse missing int %s", property); JsonNode pNode = node.get(property); diff --git a/core/src/test/java/org/apache/iceberg/TestSnapshotJson.java b/core/src/test/java/org/apache/iceberg/TestSnapshotJson.java index 130129ab3477..1ce00464cb5e 100644 --- a/core/src/test/java/org/apache/iceberg/TestSnapshotJson.java +++ b/core/src/test/java/org/apache/iceberg/TestSnapshotJson.java @@ -21,9 +21,11 @@ import java.io.File; import java.io.IOException; +import java.io.UncheckedIOException; import java.util.List; import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList; import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap; +import org.assertj.core.api.Assertions; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; @@ -148,4 +150,16 @@ public void testJsonConversionWithManifestList() throws IOException { Assert.assertNull("Summary should be null", snapshot.summary()); Assert.assertEquals("Schema ID should match", expected.schemaId(), snapshot.schemaId()); } + + @Test + public void testParseJsonWithTrailingContent() { + String validJson = SnapshotParser.toJson(new BaseSnapshot(ops.io(), System.currentTimeMillis(), 1, + "file:/tmp/manifest1.avro", "file:/tmp/manifest2.avro")); + Assertions.assertThatThrownBy(() -> SnapshotParser.fromJson(ops.io(), validJson + "{}")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Found characters after the expected end of input"); + Assertions.assertThatThrownBy(() -> SnapshotParser.fromJson(ops.io(), validJson + " some more content")) + .isInstanceOf(UncheckedIOException.class) + .hasMessage("Failed to read version from json: " + validJson + " some more content"); + } } diff --git a/core/src/test/java/org/apache/iceberg/TestSnapshotRefParser.java b/core/src/test/java/org/apache/iceberg/TestSnapshotRefParser.java index e5ade0eb7083..bd76d4a2b0f7 100644 --- a/core/src/test/java/org/apache/iceberg/TestSnapshotRefParser.java +++ b/core/src/test/java/org/apache/iceberg/TestSnapshotRefParser.java @@ -19,6 +19,8 @@ package org.apache.iceberg; +import java.io.UncheckedIOException; +import org.assertj.core.api.Assertions; import org.junit.Assert; import org.junit.Test; @@ -79,6 +81,20 @@ public void testTagFromJsonAllFields() { Assert.assertEquals("Should be able to deserialize tag with all fields", ref, SnapshotRefParser.fromJson(json)); } + @Test + public void testTagFromJsonTrailingContent() { + String validJson = "{\"snapshot-id\":1,\"type\":\"tag\"}"; + Assertions.assertThatThrownBy(() -> SnapshotRefParser.fromJson(validJson + "{}")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Found characters after the expected end of input"); + Assertions.assertThatThrownBy(() -> SnapshotRefParser.fromJson(validJson + " null")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Found characters after the expected end of input"); + Assertions.assertThatThrownBy(() -> SnapshotRefParser.fromJson(validJson + " none")) + .isInstanceOf(UncheckedIOException.class) + .hasMessage("Failed to parse snapshot ref: " + validJson + " none"); + } + @Test public void testBranchFromJsonDefault() { String json = "{\"snapshot-id\":1,\"type\":\"branch\"}"; diff --git a/core/src/test/java/org/apache/iceberg/puffin/TestFileMetadataParser.java b/core/src/test/java/org/apache/iceberg/puffin/TestFileMetadataParser.java index 5efac95bdb24..bdfa91b2fbf0 100644 --- a/core/src/test/java/org/apache/iceberg/puffin/TestFileMetadataParser.java +++ b/core/src/test/java/org/apache/iceberg/puffin/TestFileMetadataParser.java @@ -31,8 +31,8 @@ public class TestFileMetadataParser { @Test public void testInvalidJson() { assertThatThrownBy(() -> FileMetadataParser.fromJson((String) null)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("argument \"content\" is null"); + .isInstanceOf(NullPointerException.class) + .hasMessageContaining("input is null"); assertThatThrownBy(() -> FileMetadataParser.fromJson("")) .isInstanceOf(UncheckedIOException.class) @@ -45,6 +45,16 @@ public void testInvalidJson() { assertThatThrownBy(() -> FileMetadataParser.fromJson("{\"blobs\": []")) .isInstanceOf(UncheckedIOException.class) .hasMessageContaining("Unexpected end-of-input: expected close marker for Object"); + + assertThatThrownBy(() -> FileMetadataParser.fromJson("{\"blobs\": []} {}")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Found characters after the expected end of input"); + + assertThatThrownBy(() -> FileMetadataParser.fromJson("{\"blobs\": []} whatever")) + .isInstanceOf(UncheckedIOException.class) + .hasMessageStartingWith( + "com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'whatever': was expecting " + + "(JSON String, Number, Array, Object or token 'null', 'true' or 'false')"); } @Test diff --git a/core/src/test/java/org/apache/iceberg/rest/responses/TestOAuthTokenResponse.java b/core/src/test/java/org/apache/iceberg/rest/responses/TestOAuthTokenResponse.java index 260bbb5a7b88..0e4b306b90e3 100644 --- a/core/src/test/java/org/apache/iceberg/rest/responses/TestOAuthTokenResponse.java +++ b/core/src/test/java/org/apache/iceberg/rest/responses/TestOAuthTokenResponse.java @@ -21,6 +21,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; +import java.io.IOException; import java.util.Collections; import java.util.Set; import org.apache.iceberg.AssertHelpers; @@ -72,7 +73,7 @@ public void testHasOnlyKnownFields() { Set fieldsFromSpec = Sets.newHashSet(); Collections.addAll(fieldsFromSpec, allFieldsFromSpec()); try { - JsonNode node = JsonUtil.mapper().readValue(serialize(createExampleInstance()), JsonNode.class); + JsonNode node = JsonUtil.parseJson(serialize(createExampleInstance())); for (String field : fieldsFromSpec) { Assert.assertTrue("Should have field: " + field, node.has(field)); } @@ -80,7 +81,7 @@ public void testHasOnlyKnownFields() { for (String field : ((Iterable) node::fieldNames)) { Assert.assertTrue("Should not have field: " + field, fieldsFromSpec.contains(field)); } - } catch (JsonProcessingException e) { + } catch (IOException e) { throw new RuntimeException(e); } } diff --git a/core/src/test/java/org/apache/iceberg/util/TestJsonUtil.java b/core/src/test/java/org/apache/iceberg/util/TestJsonUtil.java new file mode 100644 index 000000000000..4cf2835f639a --- /dev/null +++ b/core/src/test/java/org/apache/iceberg/util/TestJsonUtil.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.iceberg.util; + +import com.fasterxml.jackson.core.JsonParseException; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import org.assertj.core.api.Assertions; +import org.junit.Test; + +public class TestJsonUtil { + @Test + public void testParseJsonString() throws IOException { + // minimal + Assertions.assertThat(JsonUtil.parseJson("{}")) + .hasToString("{}"); + + Assertions.assertThat(JsonUtil.parseJson("{ \"attribute\": 123 }")) + .hasToString("{\"attribute\":123}"); + + // leading whitespace + Assertions.assertThat(JsonUtil.parseJson(" {}")) + .hasToString("{}"); + + // trailing whitespace + Assertions.assertThat(JsonUtil.parseJson("{} ")) + .hasToString("{}"); + } + + @Test + public void testRejectTrailingStringContent() { + Assertions.assertThatThrownBy(() -> JsonUtil.parseJson("{} a")) + .isInstanceOf(JsonParseException.class) + .hasMessageStartingWith( + "Unrecognized token 'a': was expecting (JSON String, Number, Array, Object or token 'null', " + + "'true' or 'false')"); + + Assertions.assertThatThrownBy(() -> JsonUtil.parseJson("{} null")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageStartingWith("Found characters after the expected end of input"); + + Assertions.assertThatThrownBy(() -> JsonUtil.parseJson("{}{}")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageStartingWith("Found characters after the expected end of input"); + } + + @Test + public void testParseJsonStream() throws IOException { + // minimal + Assertions.assertThat(JsonUtil.parseJson(byteStream("{}"))) + .hasToString("{}"); + + Assertions.assertThat(JsonUtil.parseJson(byteStream("{ \"attribute\": 123 }"))) + .hasToString("{\"attribute\":123}"); + + // leading whitespace + Assertions.assertThat(JsonUtil.parseJson(byteStream(" {}"))) + .hasToString("{}"); + + // trailing whitespace + Assertions.assertThat(JsonUtil.parseJson(byteStream("{} "))) + .hasToString("{}"); + } + + @Test + public void testRejectTrailingStreamContent() { + Assertions.assertThatThrownBy(() -> JsonUtil.parseJson(byteStream("{} a"))) + .isInstanceOf(JsonParseException.class) + .hasMessageStartingWith( + "Unrecognized token 'a': was expecting (JSON String, Number, Array, Object or token 'null', " + + "'true' or 'false')"); + + Assertions.assertThatThrownBy(() -> JsonUtil.parseJson(byteStream("{} null"))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageStartingWith("Found characters after the expected end of input"); + + Assertions.assertThatThrownBy(() -> JsonUtil.parseJson(byteStream("{}{}"))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageStartingWith("Found characters after the expected end of input"); + } + + private InputStream byteStream(String input) { + return new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8)); + } +} diff --git a/mr/build.gradle b/mr/build.gradle index 11ec035e70d4..3c0db8102e1c 100644 --- a/mr/build.gradle +++ b/mr/build.gradle @@ -33,6 +33,8 @@ project(':iceberg-mr') { implementation project(':iceberg-hive-metastore') implementation project(':iceberg-orc') implementation project(':iceberg-parquet') + implementation "com.fasterxml.jackson.core:jackson-databind" + implementation "com.fasterxml.jackson.core:jackson-core" compileOnly("org.apache.hadoop:hadoop-client") { exclude group: 'org.apache.avro', module: 'avro' diff --git a/spark/v2.4/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java b/spark/v2.4/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java index f15c5c6536e9..6b07b6f1387d 100644 --- a/spark/v2.4/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java +++ b/spark/v2.4/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java @@ -61,7 +61,7 @@ static StreamingOffset fromJson(String json) { Preconditions.checkNotNull(json, "Cannot parse StreamingOffset JSON: null"); try { - JsonNode node = JsonUtil.mapper().readValue(json, JsonNode.class); + JsonNode node = JsonUtil.parseJson(json); // The version of StreamingOffset. The offset was created with a version number // used to validate when deserializing from json string. int version = JsonUtil.getInt(VERSION, node); diff --git a/spark/v3.0/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java b/spark/v3.0/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java index 64277ecf3be5..e91f2eedc58f 100644 --- a/spark/v3.0/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java +++ b/spark/v3.0/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java @@ -62,7 +62,7 @@ static StreamingOffset fromJson(String json) { Preconditions.checkNotNull(json, "Cannot parse StreamingOffset JSON: null"); try { - JsonNode node = JsonUtil.mapper().readValue(json, JsonNode.class); + JsonNode node = JsonUtil.parseJson(json); return fromJsonNode(node); } catch (IOException e) { throw new UncheckedIOException(String.format("Failed to parse StreamingOffset from JSON string %s", json), e); @@ -74,7 +74,7 @@ static StreamingOffset fromJson(InputStream inputStream) { JsonNode node; try { - node = JsonUtil.mapper().readValue(inputStream, JsonNode.class); + node = JsonUtil.parseJson(inputStream); } catch (IOException e) { throw new UncheckedIOException("Failed to read StreamingOffset from json", e); } diff --git a/spark/v3.1/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java b/spark/v3.1/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java index 64277ecf3be5..e91f2eedc58f 100644 --- a/spark/v3.1/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java +++ b/spark/v3.1/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java @@ -62,7 +62,7 @@ static StreamingOffset fromJson(String json) { Preconditions.checkNotNull(json, "Cannot parse StreamingOffset JSON: null"); try { - JsonNode node = JsonUtil.mapper().readValue(json, JsonNode.class); + JsonNode node = JsonUtil.parseJson(json); return fromJsonNode(node); } catch (IOException e) { throw new UncheckedIOException(String.format("Failed to parse StreamingOffset from JSON string %s", json), e); @@ -74,7 +74,7 @@ static StreamingOffset fromJson(InputStream inputStream) { JsonNode node; try { - node = JsonUtil.mapper().readValue(inputStream, JsonNode.class); + node = JsonUtil.parseJson(inputStream); } catch (IOException e) { throw new UncheckedIOException("Failed to read StreamingOffset from json", e); } diff --git a/spark/v3.2/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java b/spark/v3.2/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java index 64277ecf3be5..e91f2eedc58f 100644 --- a/spark/v3.2/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java +++ b/spark/v3.2/spark/src/main/java/org/apache/iceberg/spark/source/StreamingOffset.java @@ -62,7 +62,7 @@ static StreamingOffset fromJson(String json) { Preconditions.checkNotNull(json, "Cannot parse StreamingOffset JSON: null"); try { - JsonNode node = JsonUtil.mapper().readValue(json, JsonNode.class); + JsonNode node = JsonUtil.parseJson(json); return fromJsonNode(node); } catch (IOException e) { throw new UncheckedIOException(String.format("Failed to parse StreamingOffset from JSON string %s", json), e); @@ -74,7 +74,7 @@ static StreamingOffset fromJson(InputStream inputStream) { JsonNode node; try { - node = JsonUtil.mapper().readValue(inputStream, JsonNode.class); + node = JsonUtil.parseJson(inputStream); } catch (IOException e) { throw new UncheckedIOException("Failed to read StreamingOffset from json", e); }