public static Expression fromJson(String json) {
    return fromJson(json, null);
  }
@Test
  public void invalidValues() {
    assertThatThrownBy(
            () ->
                ExpressionParser.fromJson(
                    "{\n"
                        + "  \"type\" : \"not-nan\",\n"
                        + "  \"term\" : \"x\",\n"
                        + "  \"value\" : 34.0\n"
                        + "}"))
        .isInstanceOf(IllegalArgumentException.class)
        .hasMessage("Cannot parse NOT_NAN predicate: has invalid value field");

    assertThatThrownBy(
            () ->
                ExpressionParser.fromJson(
                    "{\n"
                        + "  \"type\" : \"is-nan\",\n"
                        + "  \"term\" : \"x\",\n"
                        + "  \"values\" : [ 34.0, 35.0 ]\n"
                        + "}"))
        .isInstanceOf(IllegalArgumentException.class)
        .hasMessage("Cannot parse IS_NAN predicate: has invalid values field");

    assertThatThrownBy(
            () ->
                ExpressionParser.fromJson(
                    "{\n"
                        + "  \"type\" : \"lt\",\n"
                        + "  \"term\" : \"x\",\n"
                        + "  \"values\" : [ 1 ]\n"
                        + "}"))
        .isInstanceOf(IllegalArgumentException.class)
        .hasMessage("Cannot parse LT predicate: missing value");

    assertThatThrownBy(
            () ->
                ExpressionParser.fromJson(
                    "{\n"
                        + "  \"type\" : \"lt\",\n"
                        + "  \"term\" : \"x\",\n"
                        + "  \"value\" : 34,\n"
                        + "  \"values\" : [ 1 ]\n"
                        + "}"))
        .isInstanceOf(IllegalArgumentException.class)
        .hasMessage("Cannot parse LT predicate: has invalid values field");

    assertThatThrownBy(
            () ->
                ExpressionParser.fromJson(
                    "{\n"
                        + "  \"type\" : \"not-in\",\n"
                        + "  \"term\" : \"x\",\n"
                        + "  \"value\" : [ 1, 2 ]\n"
                        + "}"))
        .isInstanceOf(IllegalArgumentException.class)
        .hasMessage("Cannot parse NOT_IN predicate: missing values");

    assertThatThrownBy(
            () ->
                ExpressionParser.fromJson(
                    "{\n"
                        + "  \"type\" : \"in\",\n"
                        + "  \"term\" : \"x\",\n"
                        + "  \"value\" : \"min\",\n"
                        + "  \"values\" : [ 1, 2 ]\n"
                        + "}"))
        .isInstanceOf(IllegalArgumentException.class)
        .hasMessage("Cannot parse IN predicate: has invalid value field");
  }