Code Monkey home page Code Monkey logo

Comments (11)

danivek avatar danivek commented on August 17, 2024

@wesselvdv, sorry for having breaking something... I agree with you that json-api-serializer must also follow the rule you mention.

To clarify all cases:

1. If relationship is present and is null it should output with data: null

const JSONAPISerializer = require('json-api-serializer');
const Serializer = new JSONAPISerializer();

// Schools type
Serializer.register('schools', {
  relationships: {
    students: {
      type: 'students',
      links: {
        self: '/students'
      }
    }
  }
});

// Students type
Serializer.register('students', {
  relationships: {
    grades: {
      type: 'grades',
      links: {
        self: '/grades'
      }
    }
  }
});

Serializer.register('grades');

// Input data for schools
const input = {
  "id": "1",
  "name": "School Name",
  "students": {
    id: 1,
  },
  "grades": null
};

const output = Serializer.serialize('schools', input);
console.log(JSON.stringify(output));

Output should have data: null for grades relationship:

{
  "jsonapi": {
    "version": "1.0"
  },
  "data": {
    "type": "schools",
    "id": "1",
    "attributes": {
      "name": "School Name"
    },
    "relationships": {
      "students": {
        "links": {
          "self": "/students"
        },
        "data": {
          "type": "students",
          "id": "1"
        }
      }
    }
  },
  "included": [
    {
      "type": "students",
      "id": "1",
      "attributes": {},
      "relationships": {
        "grades": {
          "links": {
            "self": "/grades"
          },
          "data": null
        }
      }
    }
  ]
}

2. Considering I revert to data:undefined if relationship is missing and it have at least one of the following links or meta property, it should output with data: undefined

const JSONAPISerializer = require('json-api-serializer');
const Serializer = new JSONAPISerializer();

// Schools type
Serializer.register('schools', {
  relationships: {
    students: {
      type: 'students',
      links: {
        self: '/students'
      }
    }
  }
});

// Students type
Serializer.register('students', {
  relationships: {
    grades: {
      type: 'grades',
      links: {
        self: '/grades'
      }
    }
  }
});

Serializer.register('grades');

// Input data for schools
const input = {
  "id": "1",
  "name": "School Name",
  "students": {
    id: 1,
  }
};

const output = Serializer.serialize('schools', input);
console.log(JSON.stringify(output));

Output should not have data for grades relationship:

{
  "jsonapi": {
    "version": "1.0"
  },
  "data": {
    "type": "schools",
    "id": "1",
    "attributes": {
      "name": "School Name"
    },
    "relationships": {
      "students": {
        "links": {
          "self": "/students"
        },
        "data": {
          "type": "students",
          "id": "1"
        }
      }
    }
  },
  "included": [
    {
      "type": "students",
      "id": "1",
      "attributes": {},
      "relationships": {
        "grades": {
          "links": {
            "self": "/grades"
          }
        }
      }
    }
  ]
}

3. Considering I revert to data: undefined If relationship is missing and NOT have at least one of the following links or meta property

const JSONAPISerializer = require('json-api-serializer');
const Serializer = new JSONAPISerializer();

// Schools type
Serializer.register('schools', {
  relationships: {
    students: {
      type: 'students',
      links: {
        self: '/students'
      }
    }
  }
});

// Students type
Serializer.register('students', {
  relationships: {
    grades: {
      type: 'grades'
    }
  }
});

Serializer.register('grades');

// Input data for schools
const input = {
  "id": "1",
  "name": "School Name",
  "students": {
    id: 1,
  }
};

Output will have empty object for grades relationship

{
  "jsonapi": {
    "version": "1.0"
  },
  "data": {
    "type": "schools",
    "id": "1",
    "attributes": {
      "name": "School Name"
    },
    "relationships": {
      "students": {
        "links": {
          "self": "/students"
        },
        "data": {
          "type": "students",
          "id": "1"
        }
      }
    }
  },
  "included": [
    {
      "type": "students",
      "id": "1",
      "attributes": {},
      "relationships": {
        "grades": {}
      }
    }
  ]
}

This case is not clear regarding the spec. I don't think "relationships": { "grades": {} }" is a valid output, because it break the following rule:

relationship object” MUST contain at least one of the following:

  • links: ...
  • data: ...
  • meta: ...

Is grades relationship object should be filtered out from relationships object in such case ?
Is grades relationship object should have at least data with null ?

@Mattii any ideas ?

from json-api-serializer.

wesselvdv avatar wesselvdv commented on August 17, 2024

@danivek I agree with the first two cases. Those appear to correspond to the json:api spec, and will make sure that the behaviour introduced by #38 is reverted.

Is grades relationship object should be filtered out from relationships object in such case ?

I wouldn't introduce this behaviour, this will cause a lot of confusion if objects just magically start disappearing.

Is grades relationship object should have at least data with null ?

I wouldn't do this either, this will cause the same situation as we have now, if I understand you correctly.

I suggest to introduce the following behaviour if a defined relationship is missing in an object that's serialised:

  • If json-api-serializer can deduce the links object, or if it has been defined by the user in the type definition, and the relationships object is missing.
    • Include the links object, make sure data is undefined, and if applicable include meta.
  • If json-api-serializer can NOT deduce the links object, the relationships object is missing and no meta has been defined.
    • Throw an exception stating that no spec compliant json:api object can be created.
  • If json-api-serializer can NOT deduce the links object, the relationships object is missing, but meta data has been defined.
    • Include the meta object and make sure data & links are undefined.

Unless I am missing something, the above should make sure that json-api-serializer always creates objects that are compliant.

from json-api-serializer.

wesselvdv avatar wesselvdv commented on August 17, 2024

@danivek thanks for the quick fix!!

from json-api-serializer.

alechirsch avatar alechirsch commented on August 17, 2024

@danivek I am seeing results that contradicts the second case in your previous comment.

I registered a type with about 15 relationships.

I fetched data without including any relationships, the resulting json includes all 15 relationships as

{
   data: null
}

I would expect that if my data does not have any relationships defined, it should not attempt to serialize them even if they are registered with my type.

from json-api-serializer.

alechirsch avatar alechirsch commented on August 17, 2024

@danivek, thoughts?

from json-api-serializer.

danivek avatar danivek commented on August 17, 2024

@alechirsch, I think it breaks JSON:API specification https://jsonapi.org/format/#document-resource-object-linkage

Resource linkage MUST be represented as one of the following:
null for empty to-one relationships.
an empty array ([]) for empty to-many relationships.

What your input data looks like ?

from json-api-serializer.

alechirsch avatar alechirsch commented on August 17, 2024

According to this, it should NOT include related resources that were not requested

https://jsonapi.org/format/#fetching-includes

If an endpoint supports the include parameter and a client supplies it, the server MUST NOT include unrequested resource objects in the included section of the compound document.

I think #35 might be related to this.

In my case, I am requesting 1 relationship in the include part of the my query. The data fetches one relationship and then it serializes ALL relationships that are registered with that type, even though the user does not request them.

from json-api-serializer.

danivek avatar danivek commented on August 17, 2024

What your input data looks like ?

json-api-serializer tries to detect if a relationship has been populated or not by checking if it is a plain object. In this case, it tries to serialize the relation and set it in included, otherwise it considers that it is an array of identifier or simply an identifier and set typeand id in the relationship data of a resource.

from json-api-serializer.

alechirsch avatar alechirsch commented on August 17, 2024

Here is an example of what I am talking about:

it('should not serialize relationships that were not provided', function(done) {
      const Serializer = new JSONAPISerializer();
      Serializer.register('people', {});
      Serializer.register('article', {
        relationships: {
          author: {
            type: 'people'
          }
        }
      });
  
      const data = {
        id: '1',
        title: 'Nice article'
      };
  
      const serialized = Serializer.serialize('article', data);
      console.log(serialized);
      
      expect(serialized.data).to.have.property('id');
      expect(serialized.data.attributes).to.have.property('title');
      expect(serialized.data.relationships).to.not.have.property('author');
      done();
    });

This produces:

{
  jsonapi: { version: '1.0' },
  meta: undefined,
  links: undefined,
  data: { type: 'article',
    id: '1',
    attributes: { title: 'Nice article' },
    relationships: { author: { data: null } },
    meta: undefined,
    links: undefined
  },
  included: undefined
}

If data has an empty object called author, then I would expect the above to be the result.
I expected this as the result

{
  jsonapi: { version: '1.0' },
  meta: undefined,
  links: undefined,
  data: { type: 'article',
    id: '1',
    attributes: { title: 'Nice article' },
    relationships: {},
    meta: undefined,
    links: undefined
  },
  included: undefined
}

Also this statement mentions empty relationships, not necessarily undefined relationships:

Resource linkage MUST be represented as one of the following:
null for empty to-one relationships.
an empty array ([]) for empty to-many relationships.

from json-api-serializer.

alechirsch avatar alechirsch commented on August 17, 2024

I would expect the code to be like this, it still produces null or empty array relationships IF the relationships are defined as empty in the data object provided.

// Line 627
if (
        serializeRelationship.data !== undefined ||
        serializeRelationship.links !== undefined ||
        serializeRelationship.meta !== undefined
      ) {
        // Convert case
        relationship = options.convertCase
          ? this._convertCase(relationship, options.convertCase)
          : relationship;
  
        serializedRelationships[relationship] = serializeRelationship;
      }

As opposed to this:

      if (
        serializeRelationship.data === undefined &&
        serializeRelationship.links === undefined &&
        serializeRelationship.meta === undefined
      ) {
        serializeRelationship = {
          data: null
        };
      }

      // Convert case
      relationship = options.convertCase
        ? this._convertCase(relationship, options.convertCase)
        : relationship;

      serializedRelationships[relationship] = serializeRelationship;

from json-api-serializer.

danivek avatar danivek commented on August 17, 2024

@alechirsch You're right, regarding the spec there's no reason for a missing relationship to be serialized as null

from json-api-serializer.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.