Transforming array of objects into named object in GROQ query
Unfortunately, GROQ doesn't have built-in functionality to dynamically create objects with keys derived from field values. You cannot directly transform your array structure into an object keyed by the day field within a GROQ query.
The limitation is that GROQ doesn't support:
- Dynamic object key creation from field values
- Functions like
object::merge()or similar reduce operations to build keyed objects - Using computed values as object keys in projections
Your best options:
1. Transform client-side (recommended)
This is the most practical approach. Query the array as-is and transform it with a simple reduce:
const result = await client.fetch(`*[_type == "yourType"][0]{ hours }`);
const hoursKeyed = result.hours.reduce((acc, item) => {
acc[item.day] = { from: item.from, to: item.to };
return acc;
}, {});2. Restructure your schema
If you frequently need this keyed format, consider storing it as an object from the start:
hours: {
monday: { from: "9:00AM", to: "5:00PM" },
tuesday: { from: "9:00AM", to: "5:00PM" },
// ...
}This eliminates transformation needs, though it's less flexible if days vary.
3. Hardcode projections (not recommended)
If you have a fixed set of days, you could manually project each:
*[_type == "location"]{
"hours": {
"monday": hours[day == "monday"][0],
"tuesday": hours[day == "tuesday"][0],
"wednesday": hours[day == "wednesday"][0]
// ... etc
}
}This works but is tedious and unmaintainable.
The bottom line: GROQ excels at querying and projecting data, not complex restructuring. For transformations like array-to-keyed-object conversions, client-side processing is the right tool. It's cleaner, more maintainable, and only adds a few lines of code.
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.