【问题标题】:How can I handle long Int with GraphQL?如何使用 GraphQL 处理 long Int?
【发布时间】:2020-11-03 16:48:14
【问题描述】:

如您所知,GraphQL 没有像 long int 这样的数据类型。所以,每当数字像10000000000 这样大的时候,它就会抛出这样的错误:Int cannot represent non 32-bit signed integer value: 1000000000000

为此,我知道两种解决方案:

  1. 使用标量。
import { GraphQLScalarType } from 'graphql';
import { makeExecutableSchema } from '@graphql-tools/schema';

const myCustomScalarType = new GraphQLScalarType({
  name: 'MyCustomScalar',
  description: 'Description of my custom scalar type',
  serialize(value) {
    let result;
    return result;
  },
  parseValue(value) {
    let result;
    return result;
  },
  parseLiteral(ast) {
    switch (ast.kind) {
    }
  }
});

const schemaString = `

scalar MyCustomScalar

type Foo {
  aField: MyCustomScalar
}

type Query {
  foo: Foo
}

`;

const resolverFunctions = {
  MyCustomScalar: myCustomScalarType
};

const jsSchema = makeExecutableSchema({
  typeDefs: schemaString,
  resolvers: resolverFunctions,
});
  1. 使用apollo-type-bigint package

这两种解决方案都将大整数转换为string,我宁愿不使用字符串(我更喜欢数字类型)。

【问题讨论】:

  • 将大整数转换为字符串”是什么意思?
  • 意味着如果我使用这种方法,那么数据应该像{ "a": "10000000000" } 但它应该是。 {"a" : 1000000000}
  • 数字过长的 JSON 很难解析,因此将它们放在字符串中更容易。鉴于任何超过 32 位的整数类型无论如何都将是自定义标量,这应该无关紧要。
  • 那么,我的第一种方法是否适合实施?或者您还有其他选择吗?
  • 好吧,您发布的代码 sn-p 实际上并没有做任何事情,但是是的,所有方法都将基于使用自定义标量类型。

标签: javascript node.js graphql bigint


【解决方案1】:

正确,graphQL 中没有 bigInt 这样的概念。

您可以尝试以下方法之一:

  1. 将类型设置为Float 而不是Int - 它将处理所有大的int 值并将它们发送为number [以下是技术选项,尽管您表示不喜欢 string 解决方案]
  2. 按照您的描述将类型设置为String
  3. 如您所述,提供(npm 提供的数据类型,例如)BigInt。它将处理大整数,但会将您的值转换为string

npm bigInt 依赖选项:

【讨论】:

  • 会检查浮动的东西。
  • "Float 将处理所有大的 int 值" - 直到 53 位。
  • @HarshPatel 并不是那么回事。 64 位和 128 位整数也很常见。
  • 我注意到一件事,如果我将数据类型设为浮点数,它将处理任何大数字,我不明白为什么。但它的奇怪行为。就像我检查 1B10B
【解决方案2】:

Graphql 引入了标量。我正在使用 Java,所以我可以用 Java 提供一些解决方案。您可以按照以下步骤实现相同的目的。

请在您的 .graphqls 文件中定义标量

scalar Long

type Movie{
movieId: String
movieName: String
producer: String
director: String
demoId : Long
}

现在你必须在你的接线中注册这个标量。

return RuntimeWiring.newRuntimeWiring().type("Query", typeWiring -> typeWiring
                .dataFetcher("allMovies", allMoviesDataFetcher).dataFetcher("movie", movieDataFetcher)
                .dataFetcher("getMovie", getMovieDataFetcher)).scalar(ExtendedScalars.GraphQLLong).build();

现在您必须为 Long 定义标量配置,如下所示。


@Configuration
public class LongScalarConfiguration {
     @Bean
        public GraphQLScalarType longScalar() {
            return GraphQLScalarType.newScalar()
                .name("Long")
                .description("Java 8 Long as scalar.")
                .coercing(new Coercing<Long, String>() {
                    @Override
                    public String serialize(final Object dataFetcherResult) {
                        if (dataFetcherResult instanceof Long) {
                            return dataFetcherResult.toString();
                        } else {
                            throw new CoercingSerializeException("Expected a Long object.");
                        }
                    }

                    @Override
                    public Long parseValue(final Object input) {
                        try {
                            if (input instanceof String) {
                                return new Long((String) input);
                            } else {
                                throw new CoercingParseValueException("Expected a String");
                            }
                        } catch (Exception e) {
                            throw new CoercingParseValueException(String.format("Not a valid Long: '%s'.", input), e
                            );
                        }
                    }

                    @Override
                    public Long parseLiteral(final Object input) {
                        if (input instanceof StringValue) {
                            try {
                                return new Long(((StringValue) input).getValue());
                            } catch (Exception e) {
                                throw new CoercingParseLiteralException(e);
                            }
                        } else {
                            throw new CoercingParseLiteralException("Expected a StringValue.");
                        }
                    }
                }).build();
        }

}

它应该可以解决您的问题。 Java相关应用请尝试一下。

【讨论】:

    【解决方案3】:

    我建议在这种情况下使用graphql-bigint 包。此实现为您提供 53 位整数。 52 位以上的任何类似整数的数字都将截断其较低的值。所以如果你需要 52bit 以上,使用字符串会更安全。

    【讨论】:

    • 这比 OP 考虑使用的 apollo-type-bigint 包更好/不同?
    • apollo-type-bigint 有两个实现。第一个仅适用于 53 位整数。第二个实现允许您使用 JavaScript 中的新数据类型 BigInt 处理 63 位整数。 graphql-bigint 更简单,如果我正确理解了这个问题,它应该可以完成 OP 需要的工作。虽然使用 apollo-type-bigint 没有错
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-07
    • 1970-01-01
    • 2010-09-05
    • 1970-01-01
    • 2016-12-16
    • 1970-01-01
    相关资源
    最近更新 更多