static AllManifestsTable.ManifestListReadTask fromJson(JsonNode jsonNode) {
    Preconditions.checkArgument(jsonNode != null, "Invalid JSON node for manifest task: null");
    Preconditions.checkArgument(
        jsonNode.isObject(), "Invalid JSON node for manifest task: non-object (%s)", jsonNode);

    Schema dataTableSchema = SchemaParser.fromJson(JsonUtil.get(DATA_TABLE_SCHEMA, jsonNode));
    FileIO fileIO = FileIOParser.fromJson(JsonUtil.get(FILE_IO, jsonNode), null);
    Schema schema = SchemaParser.fromJson(JsonUtil.get(SCHEMA, jsonNode));

    JsonNode specsArray = JsonUtil.get(SPECS, jsonNode);
    Preconditions.checkArgument(
        specsArray.isArray(), "Invalid JSON node for partition specs: non-array (%s)", specsArray);

    ImmutableList.Builder<PartitionSpec> specsBuilder = ImmutableList.builder();
    for (JsonNode specNode : specsArray) {
      PartitionSpec spec = PartitionSpecParser.fromJson(dataTableSchema, specNode);
      specsBuilder.add(spec);
    }

    Map<Integer, PartitionSpec> specsById = PartitionUtil.indexSpecs(specsBuilder.build());
    String manifestListLocation = JsonUtil.getString(MANIFEST_LIST_LOCATION, jsonNode);
    Expression residualFilter = ExpressionParser.fromJson(JsonUtil.get(RESIDUAL, jsonNode));
    long referenceSnapshotId = JsonUtil.getLong(REFERENCE_SNAPSHOT_ID, jsonNode);

    return new AllManifestsTable.ManifestListReadTask(
        dataTableSchema,
        fileIO,
        schema,
        specsById,
        manifestListLocation,
        residualFilter,
        referenceSnapshotId);
  }
@Test
  public void invalidJsonNode() throws Exception {
    String jsonStr = "{\"str\":\"1\", \"arr\":[]}";
    ObjectMapper mapper = new ObjectMapper();
    JsonNode rootNode = mapper.reader().readTree(jsonStr);

    assertThatThrownBy(() -> AllManifestsTableTaskParser.fromJson(rootNode.get("str")))
        .isInstanceOf(IllegalArgumentException.class)
        .hasMessageContaining("Invalid JSON node for manifest task: non-object ");

    assertThatThrownBy(() -> AllManifestsTableTaskParser.fromJson(rootNode.get("arr")))
        .isInstanceOf(IllegalArgumentException.class)
        .hasMessageContaining("Invalid JSON node for manifest task: non-object ");
  }