reyesoft / ngx-jsonapi

JSON API client library for Angular 5+ 👌 :: Production Ready 🚀
https://ngx-jsonapi.reyesoft.com/
MIT License
101 stars 52 forks source link

Don't include empty relationships when serializing a resource object #45

Closed danpoland closed 6 years ago

danpoland commented 6 years ago

A resource object in JSONAPI must have a type and an id. I propose that relationships that have not been set on a resource object not be serialized with an empty data object. Instead, they simply not be included in the serialization. Alternately, I propose an isRequired Boolean attribute be add to the relationship schema definition in a Service and if this is set to false and the relationship is empty don't include it in the serialization. Location of code for proposed change:https://github.com/reyesoft/ngx-jsonapi/blob/9c52a1a259c1a89fa3888fa27a167cd9e6e9734b/src/resource.ts#L111

I can find some time to work on this if one of these solutions sounds good.

pablorsk commented 6 years ago

Hi @danpoland,

when a relationship it's empty, it's empty... Now, when you have a problem with relationship?

  1. When you receive undeclarated relationship from server
  2. When you declare a relationship, but some reason, you don't receive information from server.

On case 1 or 2, why you need not define the relationship?

If you put examples, we can disccuss about that.

danpoland commented 6 years ago

HI @pablorsk , here is an example of what I am running into. Given the following Service and Resource:

import {Injectable} from '@angular/core';

import {Service, ISchema, Resource} from 'ngx-jsonapi';

@Injectable()
export class AccountService extends Service<Account> {
    public resource = Account;
    public type = 'accounts';
    public schema: ISchema = {
        relationships: {
            owner: {
                hasMany: false
            }
        }
    };
}

export class Account extends Resource {
    public attributes: {
        id: number,
        name: string
    };
}

Then in a component:

import {Component, OnInit} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';

import {AccountService, Account} from 'app/main/account/account.service';

@Component({
    selector: 'app-account-form',
    templateUrl: './account-form.component.html',
    styleUrls: ['./account-form.component.scss']
})
export class AccountFormComponent implements OnInit {
    accountForm: FormGroup;

    constructor(private formBuilder: FormBuilder,
                private accountService: AccountService) {
    }

    ngOnInit() {
        this.accountForm = this.formBuilder.group({
            name: ['', Validators.required]
        });
    }

    saveForm() {
        const account = this.accountService.new();
        account.attributes.name = this.accountForm.value.name;
        account.save();
    }
}

The call to account.save() produces an HTTP POST request to my API where the body looks like this:

{
    "data": {
        "type": "accounts",
        "id": "",
        "attributes": {
            "name": "example"
        },
        "relationships": {
            "owner": {
                "data": {}
            }
        }
    }
}

In this example owner is never set because it is an optional relationship but even though it was never set on the resource object the relationship with still serialized into the JSON object with an empty data attribute.

pablorsk commented 6 years ago

I'm thinking about your issue. If you insert a new resource, without relationship set, it's ok was empty (new resource, no related children/parent).

Whats happen on your server when you send a relationship empty? I'm think will be similar to an empty or =null, rigth?