13

I've npm installed graphql-type-json and the types. How do I use it in a code first approach, where JSONObject is the scalar in the example below.

import {Field, Int, InputType} from 'type-graphql';
import {Direction, MessageType} from '../interfaces/message.interface';

@InputType()
export class MessageInput {
    @Field()
    readonly to: string;

    @Field()
    readonly type: MessageType;

    @Field()
    readonly direction: Direction;

    @Field()
    readonly body: **JSONObject**;
}
1
  • Thanks for asking this question. The docs beg the question. Commented Aug 1, 2021 at 1:40

5 Answers 5

12

I found this method and it worked for me. Might not be the code-first approach but I guess it would suffice until you figure it out :)

import { Field, ObjectType } from 'type-graphql';
import JSON from 'graphql-type-json';

@ObjectType()
export class YourClass {
  @Field(() => JSON)
  myProperty: any;
}
Sign up to request clarification or add additional context in comments.

Comments

4

It's not super elegant, but I did it by creating a @Scalar decorated class that wraps the GraphQLJSON object:

// json.scalar.ts
import { Scalar, CustomScalar } from '@nestjs/graphql';
import * as GraphQLJSON from 'graphql-type-json';

@Scalar('JSON', type => Object)
export class JsonScalar implements CustomScalar<string, any> {
  name = GraphQLJSON.name;
  description = GraphQLJSON.description;

  serialize = GraphQLJSON.serialize;
  parseValue = GraphQLJSON.parseValue;
  parseLiteral = GraphQLJSON.parseLiteral;
}

Then I just added JsonScalar to the resolvers section in the module.

You can use it in a resolver with @Query(returns => Object), same goes with other places you need to specify type to nest, it's just Object

Nestjs should really allow us to add a scalar by object rather than class, surprised it's not a thing. I was switching from schema-first to code-first and ran into this issue.

Comments

3

You can create a @Scalar() type using the approach described in the docs

2 Comments

I dont really understand how to do it for JSON, can you please provide an example?
It looks like there is already a package out there for JSON typing in GraphQL . graphql-type-json. Otherwise it looks like you just need to add a parseValue, a serialize, and a parseLiteral method. The Nest docs show how to do it with the Date type.
1

Code first

npm install graphql-type-json or yarn add graphql-type-json

import { GraphQLJSON } from 'graphql-type-json';

type JSONValue =
    | string
    | number
    | boolean
    | null
    | { [x: string]: JSONValue }
    | Array<JSONValue>;

export class SampleModel {
  @Field(() => GraphQLJSON, { nullable: true })
  data?: JSONValue; // It can different e.g If you're using Prisma ORM => "Prisma.JsonValue" 
}

Comments

0

Using schema first here, here's what works for me, on the schema:

Foo {
  bar: Json
}

Custom

import { CustomScalar, Scalar } from '@nestjs/graphql';
import { Kind, ValueNode } from 'graphql';
import _ from 'lodash';

@Scalar('Json')
export class JsonScalar implements CustomScalar<string, any> {
  description = 'Json custom scalar type';

  parseValue(value: string): string {
    this.validateFormat(value);

    return value;
  }

  serialize(value: string): string {
    return value;
  }
  // parseLiteral is a WIP, take it with a grain of salt
  parseLiteral(ast: ValueNode): string {
    if (ast.kind !== Kind.STRING) {
      throw new Error(`The input value is not a string`);
    }

    this.validateFormat(ast.value);

    return ast.value;
  }

  private validateFormat(input: any): void {
    if (_.isNil(input) || input.constructor !== Object) throw new Error(`The input string is not in JSON format`);
  }
}

and in the resolver's module:

@Module({ providers: [ JsonScalar, ...providers })
export class FooModule(){}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.