How does Sanity's GraphQL endpoint return Portable Text as parsed JSON?

12 replies
Last updated: Nov 29, 2025
Hi! I was wondering, how does Sanity's GraphQL endpoint resolves Portable Text to raw (parsed) JSON? https://www.sanity.io/docs/graphql#portable-text-5ea9c0e79586 I am not an expert, and only asking for a co-worker. He only manages to send it as a JSON string, which means I have to use
JSON.parse
in the frontend to be able to pass it to
BlockContent
in my React app. We have a MongoDB, and using dotnet-graphql, although I do not know if these are relevant here. I am curious how it is done in JS anyway! If more context needed, please ask. 🙂
AI Update

The Sanity GraphQL endpoint returns Portable Text as raw JSON through a special field naming convention. When you have a Portable Text field in your schema, the GraphQL API automatically generates a <fieldName>Raw field that contains the Portable Text content as a JSON scalar type.

How it works

For example, if you have a field called body that contains Portable Text, the GraphQL schema will expose it as bodyRaw. This field returns the Portable Text as parsed JSON (not a JSON string), which means you can directly use it in your frontend without needing JSON.parse().

Here's what this looks like in a query:

{
  allPost {
    title
    bodyRaw
  }
}

The bodyRaw field will return the Portable Text structure as a proper JSON object, ready to be passed to your BlockContent component or any Portable Text renderer.

Why you might be getting a string

If you're receiving the Portable Text as a JSON string (requiring JSON.parse()), this is likely due to how your GraphQL client or server is handling the response. The issue might be:

  1. Your GraphQL client serialization: Some GraphQL clients might be stringifying the response
  2. dotnet-graphql configuration: The .NET GraphQL library might need configuration to properly handle JSON scalar types
  3. Custom scalar handling: You may need to define how the JSON scalar type should be handled in your GraphQL implementation

For .NET/GraphQL.NET specifically

In GraphQL.NET (which is commonly used with dotnet-graphql), you'll want to ensure you have proper JSON scalar support. GraphQL.NET provides a JsonGraphType that can handle arbitrary JSON data. The Sanity GraphQL API uses a JSON scalar for the *Raw fields, so your .NET client needs to understand how to deserialize this type.

If you're using Hot Chocolate (another popular .NET GraphQL library), it has built-in JsonType support that should handle this automatically.

The key issue is that the JSON scalar type in GraphQL is not a standard scalar like String or Int—it's a custom scalar that represents arbitrary JSON. Your .NET GraphQL client needs to be configured to treat this as an object/dictionary rather than a string.

Alternative: Consider GROQ

While Sanity supports GraphQL, I'd recommend considering GROQ (Sanity's native query language) instead. GROQ handles Portable Text more naturally and gives you more flexibility in how you query and transform your content. It also has type generation support, making it type-safe like GraphQL.

If you do need to stick with GraphQL, the key is ensuring your .NET GraphQL client properly handles JSON scalar types without stringifying them. You might need to configure a custom scalar type handler in your GraphQL client library.

Show original thread
12 replies

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?