-
-
Notifications
You must be signed in to change notification settings - Fork 596
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
Object attributes transformed in array #2198
Comments
Thanks for opening this issue!
|
The server version did not change, only the JS SDK version? Could you open a PR with a failing test that demonstrates the issue? |
Yes, the server is in 7.1. |
Could you add a test so we can verify the issue? And maybe share a simple example code here to understand how exactly you are getting to this result. |
@aclec I have added a PR with a test, see parse-community/parse-server#9174. It's using the Parse JS SDK 5.2.0. Edit: I was able to reproduce the issue, updated the test. The issue occurs when the field key is a number string. |
The issue seems to come from #2120. A field value of object Parse-SDK-JS/src/ObjectStateMutations.ts Lines 188 to 198 in 4ce1f24
I think there are 2 issues:
I suspect a broader issue with how nested fields are represented:
also in:
A nested field should be represented with dots. If instead it's represented by an object where a number key represents an array index, it conflicts with objects that contain number keys. I believe the fix in #2194 does not really address the underlying issue. It excludes A quick fix for @aclec's reported issue would be to change this check: Parse-SDK-JS/src/ObjectStateMutations.ts Line 194 in 4ce1f24
to:
This avoids that the key But the underlying issue seems to be the conflicting representation, see also #2201 where the test with key |
I see that .some() is being used. Shouldn't we, in addition to checking that it's a number, use .every() to ensure that all keys are numbers? |
I think you could be right. But I also think this whole logic should be removed, because an array cannot be represented by key names that are numbers. Number strings are valid key names in JS and MongoDB. Worst case we may have to remove the dot notation feature from the JS SDK. |
Can you merge your pull request so that I can update my SDK to the next version? We need to use dot notation to access nested values, but if it's not an array, we should not transform it. An object must stay an object. The bug did not exist before. Maybe we should revert the changes? |
#2201 treats a symptom of something that is fundamentally broken, so I'm hesitant to merge it. I believe reverting #2120 and #2194 may be the correct way forward, since it seems to be based on an incorrect implementation. That would be a breaking change for people who use the feature, but the feature was adding a bug for other people, so the trade off I believe would be justified to merge it as a simple bug fix. However, the best way forward would be to fix the underlying bug. |
I will try to create a patch today to pass the tests. The goal is not to convert an object into an array; the object should remain as is until the end. I will try today to see if we can reconcile everything. |
@mtrezza The fix for this is to improve the JSON array check. A JSON array is a json with keys index 0-n like a normal array anything else should be ignored. I’ll do a separate PR with test. |
I'm not familiar with the term "JSON array", what is that? An array in JSON syntax is using square brackets, like ["a","b"] If such an array would be represented in JSON as {"0":"a","1":"b"} then how would it be differentiated from an object const obj = {"0":"a","1":"b"}; |
You access the values the same way, this is basically how dot notation supports both json and arrays mixed internally in MongoDB.
There is JSON Objects so I call this JSON Array. Not sure what the official term is for this. |
I think I'm getting it. I understand it converts the array to an object representation so that the array becomes accessible like an object. But this conversion from array to object seems to be irreversible. Because from the output of the conversion you cannot infer anymore whether this is a representation of an array or just a normal object. For example, how can you infer from const obj = { 0: {0: 'a'}, 1: 'b' }; that it is a representation of const arr = [{0: 'a'}, 'b']; The Or the other way around: const notJSONArray = {1: 'b'}; You say it's not array because it's missing index 0. But this is also not an array, just a normal JS object: const notJSONArray = {0: 'b'}; Then again, JS allows for an array to be missing indexes in between, so only having an index 1 can also be a valid array. Maybe I'm still missing something, so I'm curious to see your PR. |
@mtrezza parse-community/parse-server#9174 will fail for the following scenario: I have fixed it slightly differently, please have a look: |
@mkmandar123 I've closed the server PR parse-community/parse-server#9174, please see #2201 for a possible fix, which however doesn't fix the underlying issue, hence the CI fails for I'm not sure about your PR, see #2198 (comment) for why that may convert objects to arrays that shouldn't be converted. I believe your fix would fail for example for |
@mtrezza I am not sure why there is a requirement of converting a jsonArray to array because data format should not change while saving any data. I believe data should remain in same format it is getting saved while retrieving the data. But if the functionality is added there would be some solid reason for having this functionality. Now I see following two outcomes.
Note: Even my test case will fail for the case |
Thanks for confirming this. That's exactly the point. How can we solve this? Can we get rid of this strange conversion? |
@mtrezza The reason for this conversion is because using Dot notation on array fields messes up the internal state of objects. If we keep @mkmandar123 fix and accept the fact that
I don't think so, can you prove it?
|
You mean when saving |
@mtrezza We can add a dot notation check too since thats the point and cause for the need of conversion. |
Would that solve the issue? What would that check look like? Maybe you can add a review code suggestion to #2201? |
A dot notation on array looks like The result from the server would return something like
|
Could you make a code suggestion in the PR? I'm not sure what this fix could look like. I have also added more cases to the test in the PR; I haven't found a solution that works for all cases. |
@mtrezza Can you make dot notation on arrays experimental? I realized that this will need some configuration on the server side. I don't want to completely remove this feature.
|
We currently do not have such a thing as experimental features (there's a long explanation somewhere why that is). We can either remove the feature as a whole or keep it with a bug until that is fixed. The bug is significant I believe, because it affects existing deployments even if the feature is not used, so maybe keeping it "as is" is not a good option. Maybe if we could isolate the bug to affect only code that is using the dot notation, then we could keep it as a bug without removing the whole feature. If we assume that this will reduce the bug's impact. Even if we made the feature experimental, it would be a breaking change for anyone using it already. So we may as well remove it altogether. Plus the larger problem with the current implementation is that it affects other features (fetching normal objects), which can introduce bugs in developer apps that are difficult to analyze. |
Let's address the issue in the original post using @mkmandar123 fix first. As for the issue with |
Even with the fixes that we considered so far, it means that objects with numbers as keys (starting with key If we keep the feature, the bug may affect a large number of deployments, as a JS object with numbers as keys doesn't sound out of the ordinary. It's also a really nasty bug to track down because the object is correctly stored in the DB, but wrong in memory when fetched. If we remove the feature we will break deployments that already use dot notation, but the feature was only released last week, so that may only be a handful. I believe removing the feature is best choice with the least impact for developers. |
Dot notation on arrays aren't supported on the server yet. Was waiting on SDK release |
The feature isn't working yet at all? That would be even better, so removing it from the JS SDK wouldn't affect anyone. That makes the choice even easier. But that also means once we add that feature, we need to add a compatibility table to the JS SDK, because this feature will require a min. version of Parse Server. |
@mtrezza We can remove the JSONArray check. This is an issue on the server side. The server converts an array to an object and sends it client side. Edit: Fixed the server side issue, parse-community/parse-server#9115 we can remove the check in the SDK. |
@dplewis Could you please take a look at the removal compared to the feature addition. I've removed the JSON array check, but there are other changes I'm not sure whether to keep or not. |
🎉 This change has been released in version 5.3.0-alpha.2 |
🎉 This change has been released in version 5.3.0-beta.1 |
🎉 This change has been released in version 5.3.0 |
New Issue Checklist
Issue Description
When I get an Object attribute on my object with Parse 5.2, it returns an array instead of the expected object.
(Parse 5.1 return an Object)
Steps to reproduce
Get an Object attribute with parse 5.2
Server
7.1
Database
MongoDB
7
Local
Client
5.2
Logs
Parse 5.1:
Parse 5.2:
The text was updated successfully, but these errors were encountered: