Closed vdkdamian closed 2 years ago
I am unable to upload objects using the saveAll() method. I get the error: "ParseError code=105 error=Invalid field name: __type."
I'm not able to replicate your issue. Some notes:
saveAll
error. Please update your issue with the codeNVMParseObject
. If you've customized a ParseObject
, it's possible your customization is creating the issueShop
a ParseObject
? If so, please post the code for it var id: String { nvmId ?? Novem.generate_nvmId() }
? Not sure if that's causing your current issue, but you are bound to run into issues with items that require Identifiable
based on the code you've shown so far. A ParseObject
comes with a default implementation of id
, 90% of use-cases should use the default implementation shown here: https://github.com/parse-community/Parse-Swift/blob/a94ac8c95d67c82cdeca870a9aeb977882d040aa/Sources/ParseSwift/Objects/ParseObject.swift#L175-L185saveAll
in Xcode 13.4.1 and Xcode 14 Beta 6 and all of it works as expected: https://github.com/parse-community/Parse-Swift/blob/a94ac8c95d67c82cdeca870a9aeb977882d040aa/ParseSwift.playground/Pages/1%20-%20Your%20first%20Object.xcplaygroundpage/Contents.swift#L148-L252 https://github.com/parse-community/Parse-Swift/blob/a94ac8c95d67c82cdeca870a9aeb977882d040aa/ParseSwift.playground/Pages/8%20-%20Pointers.xcplaygroundpage/Contents.swift#L269-L330 https://github.com/parse-community/Parse-Swift/blob/a94ac8c95d67c82cdeca870a9aeb977882d040aa/ParseSwift.playground/Pages/12%20-%20Roles%20and%20Relations.xcplaygroundpage/Contents.swift#L282-L317I recommend:
saveAll
code in Playgrounds (step 6 above) connected to your server or development server on whatever service you use to host. If this code works as expected, proceed to step 2In addition, I suspect:
init() {
self.nvmId = Novem.generate_nvmId()
}
is related to your issue based on "ParseError code=105 error=Invalid field name: __type."
The empty initialize should be "empty". If you want to create another initializer, place it in an extension and it should take at least one value. This is mentioned in the [Documentation](https://parseplatform.org/Parse-Swift/release/documentation/parseswift/parseobject/init()), in previous comments https://github.com/parse-community/Parse-Swift/pull/315#issuecomment-1014701003:
From a POP standpoint, if the ParseObject protocol doesn't require init(), developers can make non-optional values and it's impossible to initialize new versions of their ParseObject's internally in the SDK; preventing .mutable, merge, or anything else that needs a new copy inside the app. For value types with all optional properties, the compiler provides the init() automatically; assuming all other inits are defined in an extension. This is essential since this SDK doesn't use reference types and at times need to return a fresh copy of the value type to the developer.
and Playgrounds
:
Your ParseObject
should be:
struct PGRListItem: NVMParseObject {
var objectId: String?
var createdAt: Date?
var updatedAt: Date?
var ACL: ParseACL?
var originalData: Data?
/*
I highly doubt you need this here and you probably have to manage more
code in the long run because you have it here. If you really want it, it should look
more like the following. Your nvmId will only get used when there's no objectId (basically
when the ParseObject hasn't been saved to the server).
*/
// var id: String { objectId ?? nvmId ?? Novem.generate_nvmId() }
var userId: String?
var nvmId: String?
var timeStamp: Date?
var deviceId: String?
var deviceName: String?
var selected: Bool?
var shops: [Shop]?
var brand: String?
var priority: Int?
var amount: Float?
var price: [String : String]?
var checkedHistory: [Date]?
var uncheckedHistory: [Date]?
var checkedTimes: Int?
var uncheckedTimes: Int?
var lastUsed: Date?
}
/*
It is recommended to place custom initializers in an extension
to preserve the memberwise initializer.
*/
extension PGRListItem {
init(nvmId: String?) {
self.nvmId = nvmId ?? Novem.generate_nvmId()
}
}
I totally forgot I can't use custom init().
But my custom ID is for the exact reason as you mention. I had an issue where I needed the ID on objects that where not saved yet.
I'll try to reform all the mess I made later today.
I completely removed the custom init, and the custom id var. It still shows the error.
- You never posted the code you are using that "actually" produces the
saveAll
error. Please update your issue with the code
I'll do.
- Please post the complete protocol of
NVMParseObject
. If you've customized aParseObject
, it's possible your customization is creating the issue// MARK: - NVMParseObject public protocol NVMParseObject: ParseObject, NVMUserable, NVMSynchronizable, Identifiable {
/**
An ID for use by Novem instead of objectId. This id should be the same as nvmId.
- warning: Changing this would be a breaking change and can result in various issues.
*/
var id: String { get }
}
extension NVMParseObject {
/**
An ID for use by Novem instead of objectId. If no nvmId is found, it will generate a new one.
*/
func nvmId() -> String { self.nvmId ?? Novem.generate_nvmId() }
}
// MARK: - NVMSynchronizable
/* Use this protocol to allow the full synchronization of Parse Object to the Novem server. / public protocol NVMSynchronizable {
/**
A `String` used to synchronize between local en cloud.
- warning: This property is not intended to be set or modified by the developer.
- note: **This value may not be nil.** It's optional because `ParseSwift` requires there variables to be optional, but all use by the Novem framework will force-unwrap this when used. If this value is nil, the object is not correctly set and shouldn't exist.
*/
var nvmId: String? { get }
/**
A `Date` used to synchronize between local en cloud.
- warning: This property is not intended to be set or modified by the developer.
- note: **This value may not be nil.** It's optional because `ParseSwift` requires there variables to be optional, but all use by the Novem framework will force-unwrap this when used. If this value is nil, the object is not correctly set and shouldn't exist.
*/
var timeStamp: Date? { get set }
}
// MARK: - NVMUserable public protocol NVMUserable: Codable {
/**
The Novem userId for this object.
*/
var userId: String? { get set }
}
> 4. Is `Shop` a `ParseObject`? If so, please post the code for it
It's not a `ParseObject`. It's just a struct conforming to Codable
I recommend:
- Forking the repo and running all of the
saveAll
code in Playgrounds (step 6 above) connected to your server or development server on whatever service you use to host. If this code works as expected, proceed to step 2
I don't know how to connect the Playgrounds to my server. Is there a tutorial or something?
I don't know how to connect the Playgrounds to my server. Is there a tutorial or something?
This is discussed In CONTRIBUTING.md and towards the top of README.md.
I'm having the exact issue. saveAll() works for new objects (object never saved to Parse server yet) but doesn't work for modifying existing objects (object already exists on the Parse Sever).
Below is the log from Parse Sever when saveAll() is used to save existing objects. You can see that the body
contents wrong encoding of the object. No changed keys of the object are sent to the server.
verbose: REQUEST for [POST] /parse//batch: {
"requests": [
{
"body": {
"__type": "Pointer",
"className": "TestingParseObject",
"objectId": "38vPLCcGKA"
},
"method": "PUT",
"path": "/parse/classes/TestingParseObject/38vPLCcGKA"
}
],
"transaction": false
} {"body":{"requests":[{"body":{"__type":"Pointer","className":"TestingParseObject","objectId":"38vPLCcGKA"},"method":"PUT","path":"/parse/classes/TestingParseObject/38vPLCcGKA"}],"transaction":false},"headers":{"accept":"*/*","accept-encoding":"gzip, deflate","accept-language":"en-US,en;q=0.9","connection":"keep-alive","content-length":"204","content-type":"application/json","host":"147.182.187.161:1337","user-agent":"PodcastApp/1 CFNetwork/1390 Darwin/22.0.0","x-parse-application-id":"LUqHFAQFXnmfp6TN","x-parse-client-version":"swift4.14.1","x-parse-installation-id":"cecc6f78-72f6-49c0-8b44-2e7ce66b2b0e","x-parse-request-id":"d121c68b-49fc-488f-969b-ef75e2fa26b4","x-parse-session-token":"r:8b0b27669791b030b7d88ff289eab7a6"},"method":"POST","url":"/parse//batch"}
verbose: RESPONSE from [POST] /parse//batch: {
"response": [
{
"error": {
"code": 105,
"error": "Invalid field name: __type."
}
}
]
} {"result":{"response":[{"error":{"code":105,"error":"Invalid field name: __type."}}]}}
When saving new objects with saveAll() the log from Parse Server looks like this:
verbose: REQUEST for [POST] /parse//batch: {
"requests": [
{
"body": {
"ACL": {
"peYQ4RYdyp": {
"read": true,
"write": true
}
},
"favorite": true,
"hide": 0,
"playedTime": 0,
},
"method": "POST",
"path": "/parse/classes/TestingParseObject"
}
],
"transaction": false
}
verbose: RESPONSE from [POST] /parse//batch: {
"response": [
{
"success": {
"objectId": "38vPLCcGKA",
"createdAt": "2022-09-30T00:50:20.327Z"
}
}
]
} {"result":{"response":[{"success":{"createdAt":"2022-09-30T00:50:20.327Z","objectId":"38vPLCcGKA"}}]}}
The body
content is the object itself.
Digging into the source code, it looks the culprit is from this line https://github.com/parse-community/Parse-Swift/blob/a94ac8c95d67c82cdeca870a9aeb977882d040aa/Sources/ParseSwift/Coding/ParseEncoder.swift#L345. For existing objects the pointer encoding is send to the Parse Sever.
For new objects, it goes to the line https://github.com/parse-community/Parse-Swift/blob/a94ac8c95d67c82cdeca870a9aeb977882d040aa/Sources/ParseSwift/Coding/ParseEncoder.swift#L353, which encodes the object itself correctly.
Fix is working! Thanks
@bcbeta can you provide the code for your objects and your call to save? It's best to edit the Playgrounds examples and make it produce the error as mentioned here: https://github.com/parse-community/Parse-Swift/issues/405#issuecomment-1238725358. From the example you described:
when I create 2 related parse objects and save one of them
The relevant playgrounds code seems to work in my testing of the latest version: https://github.com/parse-community/Parse-Swift/blob/dc7666f774755be333f48f25c4d8bead0a1a6877/ParseSwift.playground/Pages/8%20-%20Pointers.xcplaygroundpage/Contents.swift#L101-L140
Also, if you are using save()
you have a different issue from this one. You should open a separate issue and link to not having issues until version 4.14.2
Yes sorry I deleted my comment because I need to spend a little more time describing the issue. I’ll try to get to it tonight. Something with the latest update broke my apps ability to save objects.
Something with the latest update broke my apps ability to save objects.
This is unfortunate. I ran the whole Playgrounds suite along with the CI test suite and didn't see any breaks. Feel free to open a new issue if you discover how to replicate the problem you are facing.
New Issue Checklist
Issue Description
I am unable to upload objects using the
saveAll()
method. I get the error:"ParseError code=105 error=Invalid field name: __type."
This is my struct:
Here is my code that saves the objects.
Also might be important, if only one object needs to be saved, my code makes use of
.save()
. Multiple objects use.saveAll()
. It's good to know that the.save()
function never throws this error.Steps to reproduce
Using the saveAll() method
Actual Outcome
ParseError code=105 error=Invalid field name: __type.
Expected Outcome
No error
Environment
Client
4.10.0
14.0 beta 6
iOS, macOS
iOS 16, macOS 13
Server
4.5.0
Back4app
Back4app
Database
MongoDB
3.6
Back4app
Logs