microsoftgraph / msgraph-sdk-java-core

Microsoft Graph SDK for Java - Core Library

Home Page:https://docs.microsoft.com/en-us/graph/sdks/sdks-overview

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Nullable property is not sent when patch is used: unable to delete TaskPlanner assignee (for example)

pitinono opened this issue · comments

Hello,

For an user assignment removal in a planner task, the user ID assignment object has to be null and written as is in the json sent.
But, as the Gson instance in the DefaultSerializer is not setted up with the serializeNulls() option, the null property is excluded.
So the removal is not possible, even if it is a standard behavior of the API.

Do you confirm this issue ?

What would be a workaround, without activating the serializeNulls() on the overall API to avoid unexpected behavior on other features ?

Thanks,
Renaud

Expected behavior

https://docs.microsoft.com/en-gb/graph/api/resources/plannerassignments?view=graph-rest-1.0
"The property must be set to a plannerAssignment object to create or modify assignees, and to null to remove them."

For example, to replace assignee from a planner task:

{
  "assignments": {
    "<ID to be removed user>": null,
    "<ID to be added user>": {
      "@odata.type": "#microsoft.graph.plannerAssignment",
      "orderHint": " !"
    }
  }
}

Actual behavior

Gson builder is not allowed to write null, so the line for user removal is missing when the json body is sent:

{
  "assignments": {
    "<ID to be added user>": {
      "@odata.type": "#microsoft.graph.plannerAssignment",
      "orderHint": " !"
    }
  }
}

Steps to reproduce the behavior

		// 1) Create a task assigned to me
		final User me = graphClient.me().buildRequest().get();
		final PlannerTask initialTask = new PlannerTask();
		initialTask.planId = "<Plan ID>"; // Use an existing one on which you are belonging to
		initialTask.bucketId = "<Bucket ID>"; // Use an existing one in the given plan
		initialTask.title = "Foo task";
		final PlannerAssignment initialAssignment = new PlannerAssignment();
		initialAssignment.orderHint = " !";
		initialAssignment.oDataType = "#microsoft.graph.plannerAssignment";
		initialAssignment.additionalDataManager().put("@odata.type", new JsonPrimitive("#microsoft.graph.plannerAssignment"));
		initialTask.assignments = new PlannerAssignments();
		initialTask.assignments.put(me.id, initialAssignment);

		PlannerTask createdTask = graphClient.planner().tasks().buildRequest().post(initialTask);
		createdTask = graphClient.planner().tasks(createdTask.id).buildRequest().get();

		// 2) Set task as unassigned
		final PlannerTask modifiedTask = new PlannerTask();
		modifiedTask.assignments = new PlannerAssignments();
		modifiedTask.assignments.put(me.id, null); // Missing line in serialized json

		final PlannerTaskRequest buildRequest = graphClient.planner().tasks(createdTask.id).buildRequest();
		buildRequest.addHeader("If-Match", getEtag(createdTask));
		final PlannerTask finalTask = buildRequest.patch(modifiedTask);

		// => Task is staying assigned to me

Hi @pitinono my biggest apologies for the delayed response. I believe that we currently do offer the option to serialize nulls, in order to do this I suggest the following after creating your client:

//We currently include this implementation of DefaultSerializer:
    /**
     * Creates a DefaultSerializer with an option to enable serializing of the null values.
     *
     * Serializing of null values can have side effects on the service behavior.
     * Sending null values in a PATCH request might reset existing values on the service side.
     * Sending null values in a POST request might prevent the service from assigning default values to the properties.
     * It is not recommended to send null values to the service in general and this setting should only be used when serializing information for a local store.
     *
     * @param logger         the logger
     * @param serializeNulls the setting of whether or not to serialize the null values in the JSON object
     */
    public DefaultSerializer(@Nonnull final ILogger logger, @Nonnull final boolean serializeNulls) {
        this.logger = Objects.requireNonNull(logger, "parameter logger cannot be null");
        this.gson = GsonFactory.getGsonInstance(logger, serializeNulls);
    }
    
//In your case you are certain that you want to send null values so we will make use of it here:
            
        graphClient.setSerializer(new DefaultSerializer(new DefaultLogger(), true));
//This is assuming you have not set a custom logger yourself and are using the base logger which comes standard in our library of requests, if you have a custom logger set that here as well.
//Setting 'true' here should allow you to send the null values you are expecting to send. 

Once again, apologies for the very delayed response. I hope the following is able to help. Thanks!

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.