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
fix: Allows valid non-object JSON to be retrieved in simple-json columns #6574
Conversation
Looks like this should also drop the tests related to #4440 ? Otherwise they fail. |
Yep, thanks @imnotjames. I had reverted that test previously, but failed to update it to align with expected behavior. In terms of standard operating procedure for the project, should the entire set of tests for #4440 be dropped, or should they be left in-place but updated for expected functionality? |
so, I have the same comment as in #6335
we can't have changes back and forward depend on different user needs. We need a vote before this can be merged. |
The original issue in #4440 (fixed in #4476) looks like it could have been caused by a lack of data validation for the entity, which caused an invalid JSON object to be stored in the db and throw an error when loaded back into the entity. Although, the issue makes no mention of what the data looks like that was assigned to the As @svvac mentioned in #5125, adding additional "magic" around the One major downside to the current implementation (always returning an object when loading a |
|
|
Scratch that on the previous comment - I think #4440 was using Under the typeorm posgres driver, I can replicate this case locally, but:
They were then able to switch to using the native json via In other words, maybe a bit of user error there? |
With these changes, Typeorm still tries to « fix » values it doesn't understand (= data that doesn't fit the specified model), and still does so silently, leading to potential data loss. I don't think an ORM library should take this responsibility. Let's say I carelessly save a large JSON payload larger that the column datatype and it gets truncated in the DB. I don't want that this (admittedly invalid) column to get wiped on the next save call with no indication. In that case the library should crash (because of unmet expectation : data must be valid JSON), so I can tell something is wrong, fix it, and have the opportunity to salvage what I can from my junk row. I do see why the empty string could get special treatment, especially since some backends don't allow setting default values on |
I'd agree with this.
The direct example from #4440 is that you set the
I'd agree with this, too. Perhaps |
Yes that seems to be the original problem the fix was trying to address. However my point was more generally about returning a default when
Sounds like a good first line of defense against a DB/model configuration mismatch. |
Looking at how other places handle this - for example, the MySQL driver has to handle typeorm/src/driver/mysql/MysqlDriver.ts Line 494 in 3227c0b
If it's a string it tries to parse it. If it's not a string it does not parse it. |
I've updated this PR based on the latest conversation. This fully reverts the change from #4440 (seen here, https://github.com/typeorm/typeorm/pull/4476/files#diff-f0f40758177783349c31da1ee0725addL173) and also implements an error when the value is non-string.
Although, as @imnotjames points out in the above comment, drivers handle a JSON field differently, I've implemented the error approach when the value is not a string. Obviously, this will prevent data destruction as mentioned above.
Could you elaborate, @imnotjames or @svvac? I don't necessarily see why an empty string should be handled as a special case. For back ends that don't support setting a default, do they not generally default to null naturally? Any defaults should be the responsibility of the user to implement as part of their column definition. When it comes to empty strings, I would expect they can be a valid value as
|
The problem is with an empty string from the database since
Agreed.
I kinda seem to remember some database backends defaulting to an empty string for some columns types, though I can't seem to find anything on that front right now so it's likely I'm just mistaken.
Your latest revision will choke on On that note it might be worth to point out that a That may or may not be a problem, though I'm pretty sure this was the behaviour in place before #4476. |
Yep, you're totally right. Just fixed that to allow nulls through to JSON.parse.
I agree that this probably isn't an issue due to the fact that whether it's a db null or a JSON null, they both essentially mean the same thing. |
Yes, but That being said, coalescing js- Either way that's something that should be mentioned in the docs somewhere. |
After my last push/test, I saw that It seems the best course of action is the original implementation:
Within the |
await repo.save(post); | ||
const postFound = await repo.findOne(1); | ||
postFound!.id.should.eql(1); | ||
expect(postFound!.jsonField).to.eql("null"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This expectation is now specifically noted in the docs for simple-json
.
Any thoughts on getting this merged in? Again, the original behavior before the breaking change (which was not noted as a breaking change in the changelog) seems to be the best behavior for the expectation of the functionality. This PR reverts that breaking change. |
If anyone needs this, I have this run at startup in my app as a patch until we get a fix:
|
Rebased against master. |
🤔 For some reason a completely unrelated test brought in via #6634 referenced a file in test for 4440. That's.. odd. I'll fix it first and then rebase again. |
…mpty object after a JSON parse failure
I'm refactoring some of the tests you wrote to handle a few more cases and codify the error cases. |
Closes #5501.
A breaking change / bug was introduced in #4476 as a proposed fix for #4440 (which really just needed a try/catch). It assumes that all
simple-json
type properties should be objects, and returns{}
in all other cases. However, that goes against the spec forJSON.parse()
which can return an object, array, string, number, or null. Ultimately, this breaks all existingsimple-json
properties which are non-objects.A similar fix was implemented in #5125 and has a conversation around it. However, no tests were added to that PR, and the build is failing. I've created this PR in hopes of getting this out sooner than later, because it's breaking my application.
#6335 is also a duplicate.