-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Define type of content of Json
field
#3219
Comments
This comment has been minimized.
This comment has been minimized.
Yes, but i don't understand how it can help in this problem. I may be wrong, but you cannot define the shape of the Json field using this tutorial.. |
Interesting idea, though all fields should be nullable since there is no guarantee for JSON format enforced by the database. |
Probably, if the database you are using does not have JSON support, then you simply cannot use the Json field type and this feature. |
I think @Sytten is talking about the fact in Json type say in postgres doesn't enforce any schema. It will not guarantee that all data there follows the shape you define. The proposal you have defined here is will all be enforced on application level. Also, @MaximNd why not define a 1-1 relation here if you want a schema to be maintained, just interested to know. The main selling point of Json type personally for me is it allows me to throw data in it without worrying about it's shape. |
Yes you are right. In this example I can define a 1-1 relationship, or if I store an array in a Json field, I can define a 1-m relationship. But sometimes, when you have a simple data structure (for example, only a few fields) and you know that this json data will be relate only to this entry, then it is easier to define a Json field. The advantage of this is that you don't need to run an additional query or use JOINS to get the relational data. There might also be a rare case when some users that move their database from NoSql like Mongo to relational database. And there will be a lot of destructured data. |
Being able to type your Json fields is a simple and understandable feature requests. Although there might be workarounds, this might very well be something that Prisma could offer in the future on its own - so having this feature request is valid. |
I have tried the following workaround. It works fine, until I need a field other than number or string, e.g.
Any suggestions? |
@husayt What is this approach? I googled "InputJsonObject" and prisma and only came up with this post and prisma/docs#669 which only has "InputJsonObject" in a list |
A note on potential interaction with #2431 and #2444: As JSON may be used for static or dynamic content, this should be opt in - though ideally, you could still select and filter on specific keys even if you have not typed the JSON field. In the specific use case I'm thinking of, I would actually maintain a separate table that would define which rows contain which keys. Specifically, I have a puzzle with multiple solutions. A solution has a JSON field defining some details which depend on the configuration of the puzzle it is for. |
I just ran into a need for this similar to OP's - I am using JSON as a way to store reliably structured data that is small, has several child fields, and is always 1:1 linked with the parent. Because of that, it feels wasteful to break it out into another table and require JOINs on every query. I was expecting something to be available that was akin to the custom generator client {
provider = "prisma-client-js"
scalarDefinitions {
RuleContents = "../../../prisma-scalars/RuleContents.ts"
}
}
scalar RuleContents @underlyingType(Json)
model Rule {
id String @id @default(uuid())
rejectRule RuleContents?
favoriteRule RuleContents?
} Then the referenced Typescript file would export an interface with the same name as your scalar. In the simplest form, the client would just be applying a cast for data read from the DB and type checking on data written to or queried from it. As an optional future enhancement the scalar definition file might even be able to export a custom serialize and deserialize function that the Prisma client would use to transform data before writing to/reading from the database. Finally, if you were generating a client where the scalar type wasn't provided, the client could fall back to the |
This would be a huge lifesaver! Right now I have to cast each property to unknown and then my own type, while also removing the need of having our own handling for JSON types. |
I don't want to start a bad trend here, but +1 from me too! I'd like to be able to customize/extend Json column types in TypeScript. Thanks for all your work here 🔺! |
Solved the issue with typechecking in Nest.js application by using class-transformer's classToPlain + plainToClass: |
Yes really mainly because MongoDB is now supported we needed a deep level type-safety, and will also be applicable to Postgres JSON data type @glebbash solutions works as of now. But at the end you will also wanted a single source of truth, your schema.prisma file |
Client Extensions definitely are not the solution to this issue, but they probably make a more maintainable and working workaround than before was possible. We'll keep this issue open for the actual, proper type support for |
prisma-json-types-generator is working very well to solve this for now, you should try it. |
This is an open source tool that we all use for free. It's fine that a feature request has remained open.
…On Fri, Jul 07, 2023 at 10:30 AM, Mohamed El Mahallawy < ***@***.*** > wrote:
The fact that this has been open since August 2020 is...
—
Reply to this email directly, view it on GitHub (
#3219 (comment) ) , or
unsubscribe (
https://github.com/notifications/unsubscribe-auth/AQIFNCLNKCZMWONVSY5KPDTXPBBSVANCNFSM4PWKOEXQ
).
You are receiving this because you are subscribed to this thread. Message
ID: <prisma/prisma/issues/3219/1625723312 @ github. com>
|
I am using trpc and prisma together, and the json data returned by the server has no type, which is a serious problem. But I don't think prisma should be allowed to specify the type for json data. Maybe it is safer to use some tools to verify and specify the type. I found that using the result extension can effectively specify a type for a field.(for post a reply I'm using translation software) import { PrismaClient } from "@prisma/client";
import { z } from "zod";
const goodsSchema = z
.array(
z.object({
name: z.string(),
count: z.number()
})
)
.optional();
export const db = new PrismaClient().$extends({
result: {
warehouse: {
goods: {
needs: {goods: true },
compute(warehouse) {
// if you don't want to throw error you can use .safeParse
return goodsSchema.parse(room.goods);
},
},
},
},
}); |
I think that both approaches should not be incompatible. If you plan on having a predefined JSON structure, this code you wrote could be generated by Prisma. |
Prisma Json Types Generator@3+ is stable and ready to be used with Prisma@5+. We also removed support for Prisma@4. |
@arthurfiorette Did you by any chance got time to set up an example of this? We tried adding a
We then added the path in our tsconfig:
our prisma schema includes this config:
We then want to use it like this:
|
Hey @pieterjandebruyne prisma-json-types-generator has its own repository outside of prisma. Please open a issue there. Don't need to spam this prisma thread.
Not a issue with our side. you are not including .d.ts correctly inside your tsconfig as youself said .ts file will work. What's the problem with .ts file? isn't it like what we use to code the rest of the application? Idk, dts files inside src have multiple behaviors for multiple setups and compilerOptions, too much trouble to be debugging out why typescript is not recognizing it. I think you can just add a |
+1! The only way to assign types I've found is either by double typecasting or converting to string and json const ex1 = orderFilledFields as unknown as App.Field[] // Using Object[] instead of unknown also seems to work
const ex2 = JSON.parse(JSON.stringify(orderFilledFields)) as App.Field[] This is especially annoying because in a library such as SvelteKit, typescript raises errors if you try to iterate through a |
I'm aware of this repository, but I am also voicing support for this to be a standard library feature alongside 496 others. |
sooooooo, where we at? 👀 seems like this would be a very useful feature, especially if nosql used. Is there any news on the progress from Prisma side about this? |
Hey all, happy new year! |
I've only POC'ed Prisma, but I would try an ORM that has typed JSON support like Sequelize or TypeORM. |
Mikro ORM is really neat and iirc, this worked fine (with PostgreSQL). |
Generally, yes, you are correct. But when to use JSON and when to model your data as individual tables is not really the point here. It has it's uses. Like when you have a very complex and deeply nested bit of data that is completely self contained, then a JSON column might make sense. |
Despite prisma not having direct support for typed JSON, the prisma-json-types-generator package can solve this problem for you. Prisma can have a neat DX, specially for newer devs. |
we're using prisma-json-types-generator and it makes the life better in regards to output types, but the inputs and queries are not typed accordingly, sub-queries inside not possible (and not typed), indexes via prisma don't work on json fields, not to mention unique indexes, there might be more features missing. We created input/output wrappers for the relevant entities using zod. this also helps us to infer the type from zod for the types-generator. works quite nice, but still does feel hacky and brittle. |
@arthurfiorette : As mentioned above... if queries are not typed, how does this solve the problem "completely"? |
@janpio I recently stumbled across this while trying to forward the Has the team considered exposing the model payload scalar for type augmentation in user land? A small change in how the The same principle could also apply for Example
/**
* This interface allows for custom scalar(s) via TS module augmentation.
* To override, extend with a "$user" property containing your custom scalar(s).
*/
export interface $UserExtensionScalar = {}
export type $UserScalar = {
id: string;
metadata: Prisma.JsonValue;
/* ... */
}
export type $UserPayload<ExtArgs extends $Extensions.InternalArgs = $Extensions.DefaultArgs> = {
name: "User"
objects: {}
composites: {}
scalars: $Extensions.GetPayloadResult<
$UserExtensionScalar extends { $user: infer Scalar } ? Scalar : $UserScalar,
ExtArgs["result"]["user"]
>
};
declare module '@prisma/client' {
namespace Prisma {
export interface $UserExtensionScalar {
$user: {
id: string;
metadata: { created_at: string; }
}
}
}
} |
I’m happy to say that ZenStack, built on top of Prisma, has supported this in the latest v2.8.0 version. You can define it in the schema like: type Address {
state String
city String
zip String
}
type Profile {
name String
age Int
address Address?
}
model User {
id Int @default(autoincrement()) @id
profile Profile @json
} Here is the official doc and a blog post. We would love to hear your feedback on it! |
Problem
Right now if you have the following schema with Json field:
You'll end up with a problem that you don't have strict type for
extendedProfile
field in.ts
.The one way to fix it, is specify some interface in your code and use it like this:
But it's not really comfortable to use it like that each time.
Also we can create some class and create instance of it like that:
But this solution creates some overhead due to the creation of an additional object.
Suggested solution
Maybe we can specify type in
schema.prisma
file like that?Alternatives
Alternatively, we can somehow manage this in the typescript.
The text was updated successfully, but these errors were encountered: