I'm using [email protected]. I'm using classes to define my models, and some of them have a toJSON() function defined to ensure that things are transformed appropriately, as per the JSON.stringify() specification.
apollo-server ignores the supplied function.
import { ApolloServer, makeExecutableSchema } from 'apollo-server'
const schema = makeExecutableSchema({
typeDefs: `
type Query {
myData: Data
}
type Data {
foo: String!
}
`,
resolvers: {
Query: {
myData () {
return {
foo: 'This should not show up',
toJSON () {
return {
foo: 'This *should* show up',
}
},
}
},
},
},
})
const server = new ApolloServer({ schema })
server.listen(3000)
Executing the following query:
query {
myData {
foo
}
}
Yields:
{
"data": {
"myData": {
"foo": "This should not show up"
}
}
}
Instead, I would expect it to show:
{
"data": {
"myData": {
"foo": "This *should* show up"
}
}
}
My use case is specifically involving ObjectID from mongodb, where trying to serialize directly gives the following error:
ID cannot represent value: { _bsontype: \"ObjectID\", id: <Buffer 5b 97 b1 13 09 41 c7 a3 ef 5c 40 ad> }
I should be able to write a single toJSON() that transforms the id to a string, so that I don't get this error. As it stands, I have to write a specific resolver for each id field in each to ensure that this gets handled correctly.
I'm using
[email protected]. I'm using classes to define my models, and some of them have atoJSON()function defined to ensure that things are transformed appropriately, as per theJSON.stringify()specification.
apollo-serverignores the supplied function.Simple reproduction case
import { ApolloServer, makeExecutableSchema } from 'apollo-server' const schema = makeExecutableSchema({ typeDefs: ` type Query { myData: Data } type Data { foo: String! } `, resolvers: { Query: { myData () { return { foo: 'This should not show up', toJSON () { return { foo: 'This *should* show up', } }, } }, }, }, }) const server = new ApolloServer({ schema }) server.listen(3000)Executing the following query:
query { myData { foo } }Yields:
{ "data": { "myData": { "foo": "This should not show up" } } }Instead, I would expect it to show:
{ "data": { "myData": { "foo": "This *should* show up" } } }My scenario
My use case is specifically involving
ObjectIDfrommongodb, where trying to serialize directly gives the following error:ID cannot represent value: { _bsontype: \"ObjectID\", id: <Buffer 5b 97 b1 13 09 41 c7 a3 ef 5c 40 ad> }I should be able to write a single
toJSON()that transforms the id to a string, so that I don't get this error. As it stands, I have to write a specific resolver for each id field in each to ensure that this gets handled correctly.
https://github.com/apollographql/apollo-server/issues/1633#issuecomment-419916875
I actually ended up creating a new scalar type.
scalar ObjectID
import { GraphQLScalarType } from 'graphql'
import { Kind } from 'graphql/language'
import { ObjectID } from 'mongodb'
export const resolvers = {
ObjectID: new GraphQLScalarType({
name: 'ObjectID',
description: 'The `ObjectID` scalar type represents a [`BSON`](https://en.wikipedia.org/wiki/BSON) ID commonly used in `mongodb`.',
serialize (_id) {
if (_id instanceof ObjectID) {
return _id.toHexString()
} else if (typeof _id === 'string') {
return _id
} else {
throw new Error(`${Object.getPrototypeOf(_id).constructor.name} not convertible to `)
}
},
parseValue (_id) {
if (typeof _id === 'string') {
return ObjectID.createFromHexString(_id)
} else {
throw new Error(`${typeof _id} not convertible to ObjectID`)
}
},
parseLiteral (ast) {
if (ast.kind === Kind.STRING) {
return ObjectID.createFromHexString(ast.value)
} else {
throw new Error(`${ast.kind} not convertible to ObjectID`)
}
},
}),
}
this is not user friendly at all.
Has this problem been fixed in the meantime?
We used to do stuff like id: obj => obj._id.toHexString() in all our resolvers that handled MongoDB ObjectIds, but now it seems id: obj => obj._id alone is working perfectly fine.
Most helpful comment
I actually ended up creating a new scalar type.
typeDef:
resolver: