I'm attempting to update a user's secondary information (addresses, emails, externalIds, ims, phones, organizations, relationships - the things listed on the patch page that are arrays and such). I'm successfully able to authenticate, add new information (one or more at a time) and remove one as long as it leaves one remaining (I update the JArray leaving everything but the one I want).
So, if I have 3 addresses I can remove one or two and it updates appropriately. I can easily use a patch to clear and update normal information like the first and last name, rename users and update passwords.
However, if I try to remove ALL of one type of information, nothing happens. I have tried setting the user address property to null as well as an empty List or Array. Through debugging I have verified the user patch it's sending out is accurate, but nothing seems to happen server-side.
I tried using a full Update, as well and again using null or empty lists, but the same issue happens.
What do I need to do to fully clean out one of these properties?
Example code:
//Try both a full user for an update and a blank user for a patch
User uRetrieved = directoryServiceDict[Domain].Users.Get(fullEmail).Execute();
User uPatch = new User();
uPatch.Addresses = null;
uRetrieved.Addresses = new List<Address>();
//try both a patch and update
directoryServiceDict[Domain].Users.Patch(uPatch, u.PrimaryEmail).Execute();
directoryServiceDict[Domain].Users.Update(uRetrieved, u.PrimaryEmail).Execute();
Update: I ran a series of tests, trying to pass anything I could but nothing had worked. After digging in the API source code I found that I could call the service's Serializer method to see what it's piping out, and I found that assigning it an empty string, and empty list, a list with one empty string, a new Address (for example) object and a list with an new Address object all didn't work. The serializer threw them as expected, however.
If I set it to null, though, it was ignored.
Upon reviewing the patch semantics page I see the following:
To delete a field, specify the field and set it to null. For example, "comment": null. You can also delete an entire object (if it is mutable) by setting it to null.
Looking at the given examples, they want the data to show up like {"addresses":null}
and not like any of the other variations such as {"addresses":""}
, {"addresses":[]}
or {"addresses":[""]}
.
After spending some time digging in to the API code I was able to find line 42 of the Serializer they use in which they set the serializer settings to ignore null (I assume to help keep data amounts lower for patching, for example).
This works for most things, but means when trying to Patch or Update, the serializer is ignoring the values set as null and therefore the server is not seeing that entry and won't delete it.
So, I'm working on trying to figure out the best way to fix this. There are some other posts here on StackOverflow I'm going to look at, and hopefully I'll be able to work it out (unless someone gets to it first). If I do, I'll post an answer.
Update 2: I was able to get the code to print out a serialized string including the Null by creating a new Customizer for the String type. Each time the code is run it generates a customized NullToken (basically a generated GUID that I tacked a word on to) that is set as the string value of the field I want to delete. Then when the serializer hits a string, it checks to see if the string matches the NullToken or not. If it does, I use a jsonWriter method of WriteNull()
. Otherwise, I just pass it to the general WriteValue()
.
I then just had to customize a series of classes (the Initializer that gets passed to the Service, the NewtonsoftJsonSerializer that is part of the Initializer and the Customizer that is added to the NJS settings) and set those up to be used instead of the defaults when creating the service.
Now my code properly pumps out something like {"addresses":null}
and I am happy about that.
Unfortunately it still doesn't work. I did some more testing in the API explorer and realized even though the returned object shows an update of what you put in, nothing actually is happening. I don't think it's deleting at all and therefore I have opened an issue for the API itself. If it turns out to be my own fault, I'll throw an answer here.
Summary: I'm now fairly certain the issue is in the Google API itself.