dustinfarris/ember-django-adapter

Response with nested errors

Closed this issue · 4 comments

Hi,

I'm maintaining an application where the error response from the server is given like this:

{"address":{"location":["This field may not be null."]}}

This results in a Uncaught TypeError: payload[key].forEach is not a function.

To get around it I have modified the _drfToJsonAPIValidationErrors function to look like this:

  _drfToJsonAPIValidationErrors: function(payload, keyprefix = '') {
    let out = [];
    for (let key in payload) {
      if (payload.hasOwnProperty(key)) {
        if (Object.prototype.toString.call( payload[key] ) === '[object Array]') {
          payload[key].forEach((error) => {
            if (key === this.get('nonFieldErrorsKey')) {
              out.push({
                source: { pointer: '/data' },
                detail: error,
                title: 'Validation Error'
              });
            } else {
              out.push({
                source: { pointer: `/data/attributes/${keyprefix}${key}` },
                detail: error,
                title: 'Invalid Attribute'
              });
            }
          });
        } else {
          // should this be "key." or "key/" ?
          out = out.concat(this._drfToJsonAPIValidationErrors(payload[key], `${keyprefix}${key}.`));
        }
      }
    }
    return out;
  },

While this is good enough for me, could this be beneficial to others? Should I submit a PR?
And, should the nested keys be split with a "." or a "/" (so "/data/attributes/address/location" or "/data/attributes/address.location")?


And just in case this info is valuable, I'm using ember-data.model-fragments to handle the model with nested attributes.

// models/task.js
export default DS.Model.extend(MapMarkerMixin, {
  contact: DS.hasOneFragment('contact'),
  address: DS.hasOneFragment('address'),
  // ... other fields
});

// models/address.js
export default DS.ModelFragment.extend({
  location: DS.hasOneFragment('location'),
  // ... other fields
});

Thanks! :)

Thanks for reporting. Would you mind sharing an example of a DRF serializer that would produce nested errors such as this?

peec commented

@dustinfarris

Just got this issue as well I have a customer model that includes the "user" relation (one-to-one) and getting this:,

Example output that will make exception:

{"account":{"first_name":["This field may not be null."],"email":["This field may not be null."],"last_name":["This field may not be null."]}}

Causes this JS error:

Uncaught TypeError: payload[key].forEach is not a function
exports.default.DS.default.RESTAdapter.extend._drfToJsonAPIValidationErrors._loop 
@ drf.js:118_drfToJsonAPIValidationErrors 
@ drf.js:137handleResponse 
@ drf.js:91superFunction 
@ ember.debug.js:17013handleResponse 
@ data-adapter-mixin.js:59apply

The related DRF serializer:


class CustomerSerializer(serializers.ModelSerializer):
    account = UserSerializer(read_only=False)
    # .... 

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ('id', 'url', 'username', 'first_name', 'email', 'last_name','user_permissions', 'groups', )
        extra_kwargs = {
            'user_permissions': {'read_only': True},
            'username': {'read_only': True},
            'is_active': {'read_only': True},
            'groups': {'read_only': True}
        }

Great, thanks for the example code. I'll look into this.