Skip to content
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

Serializing array issue #107

Open
stesvis opened this issue Aug 20, 2019 · 3 comments
Open

Serializing array issue #107

stesvis opened this issue Aug 20, 2019 · 3 comments

Comments

@stesvis
Copy link

stesvis commented Aug 20, 2019

Hello,

I have this class VLRideDTO (simplified version here) with a property Variants that is a collection of VLVariantDTO:

public class VLRideDTO 
{
	[JsonProperty("type")]
	public string Type { get; set; } = "rides";
	
	[JsonProperty("id")]
	public int Id { get; set; }

	[JsonProperty("variants")]
	public ICollection<VLVariantDTO> Variants { get; set; }
	
}

public class VLVariantDTO
{
	public string Type { get; set; } = "variant";

	[JsonProperty("id")]
	public int Id { get; set; }

	[JsonProperty("frame-size")]
	public string FrameSize { get; set; }

	[JsonProperty("rider-height")]
	public string RiderHeight { get; set; }
}

When I serialize it using JsonConvert.SerializeObject(data, new JsonApiSerializerSettings()) I notice that there is only one Variant under included:

{
  "data": {
    "type": "rides",
    "attributes": {
    },
    "relationships": {
      "variants": {
        "data": [
          {
            "id": null,
            "type": "variant"
          },
          {
            "id": null,
            "type": "variant"
          }
        ]
      },
    }
  },
  "included": [
    {
      "type": "variant",
      "attributes": {
        "frame-size": "57",
        "rider-height": "Any Height"
      }
    },
  ]
}

For debugging purpose, I am pasting the serialization result when I use just JsonConvert.SerializeObject(data):

{
  "type": "rides",
  "variants": [
    {
      "type": "variant",
      "frame-size": "47",
      "rider-height": "Any Height",
      "id": null,
    },
    {
      "type": "variant",
      "frame-size": "57",
      "rider-height": "Any Height",
      "id": null,
    }
  ],
  "id": null,
}

As you can see, there's supposed to be two variants.

What am I doing wrong? How can I get both variants to end up in the json:api format?

Thanks!

@alex-davies
Copy link
Collaborator

id and type have to uniquely identify a resource object. Although you have two variants, they both have the same id (null) and the same type variant

without a unique id there is no way to determine which items from the included are being referenced

are variants suppose to be resource objects in your system? if so they should have an id, if not remove the id property and they will be treated as attributes

@stesvis
Copy link
Author

stesvis commented Aug 21, 2019

Hi thanks,

This happens during creation, so i POST those variants to the API and i don't have the id yet.
If i remove the id, then when i do a GET or a PUT i will still need it tho.
What would you suggest? Should i assign random id to each? The API will ignore it anyway during a POST...

@alex-davies
Copy link
Collaborator

From the specification (https://jsonapi.org/format/#document-resource-identifier-objects)

A “resource identifier object” MUST contain type and id members.

Root objects can get away without an Id (as described on https://jsonapi.org/format/#crud-creating) however linked objects have to exist to form a relationship

I think the intended json:api way is two separate POST requests would be done to create the variant resource objects, then with the ids from the created variants you would provide them when POSTing the rides

Although i'm aware that is probably not how your APIs were designed to handle it, giving the variants ids will allow the serializer to handle it so you can get it to the server

I'm not sure how we could build support for this in the serializer as having multiple null ids does not make sense as we cant reference them. If you were to list all null ids in included, you would have no way to knowing which included item is referenced. For example if you had another field public VLVariantDTO DefaultVariant there would be no way to determine which included items are for DefaultVariant and which ones are for the Variants array

It could be argued that the serializer should throw an error in this case, we didn't go down that route as it is particularly difficult to track down errors when the particular value of a property causes the serializer to throw, and in most cases it was thought that it is better to not stop the entire response if only part of it is suspicious

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants