Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    DataSource operationBindings not respecting responseDataSchema with JSON results

    Hi,

    I have a DataSource that returns JSON objects where the request fields are not the same as the response schema. OperationBindings.responseDataSchema exists for my purpose but does not appear to work for JSON result sets.

    I traced the problem to the validateJSONRecord() method always calling 'this.getFieldNames()' on the requesting DataSource and not considering whether responseDataSchema has been set.

    Please find below an enhancement that means responseDataSchema is respected with JSON results. Please feel welcome to incorporate the changes into the mainline of your codebase.


    _handleJSONReply in ISC_DataBinding.js was modified with the call to the recordsFromObjects method being replaced as follows:
    Code:
    var responseDataSchema = this.getOperationBinding(dsRequest).responseDataSchema;
    data = this.recordsFromObjects(data, responseDataSchema);
    The following functions were replaced in ISC_DataBinding.js:
    Code:
        recordsFromObjects : function (data, schema) {
    
            // normalize to Array and apply schema
            if (!isc.isAn.Array(data)) data = [data];
    
            // skipping validation means eg date values specified as Strings won't become Dates,
            // valueXPath and dropExtraFields won't apply, etc.  But for large data volumes where
            // these features aren't required, this is faster.  Undocumented for now.
            if (this.skipJSONValidation) return data;
    
            for (var i = 0; i < data.length; i++) {
                data[i] = this.validateJSONRecord(data[i], null, schema);
            }
            return data;
        },
    
        validateJSONRecord : function (record, disableXPath, schema) {
            // If no record was given, return null.
            if (!record) {
                return null;
            }
            if ( schema == null ) {
                schema = this;
            }
            
            var fieldNames = schema.getFieldNames(),
                result = {};
            for (var i = 0; i < fieldNames.length; i++) {
                var fieldName = fieldNames[i],
                    field = schema.getField(fieldName),
                    fieldValue;
    
                if (field.valueXPath && !disableXPath) {
                    fieldValue = isc.xml.selectObjects(record, field.valueXPath, true);
                } else {
                    fieldValue = record[fieldName];
                }
    
                if (field.getFieldValue) {
                    if (!isc.isA.Function(field.getFieldValue)) {
                        isc.Func.replaceWithMethod(field, "getFieldValue",
                                                         "record,value,field,fieldName");
                    }
                    fieldValue = field.getFieldValue(record, fieldValue, field, fieldName);
                }
    
                var undef;
                if (fieldValue !== undef) {
                    // validation fieldValue, if it is complex type
                    var fieldDS = isc.DS.get(field.type);
                    if (fieldDS && !(fieldDS.skipJSONValidation)) {
                        if (!(isc.isAn.Array(fieldValue))) {
                            fieldValue = fieldDS.validateJSONRecord(fieldValue);
                        } else {
                            for (var j = 0; j < fieldValue.length; j++) {
                                fieldValue[j] = fieldDS.validateJSONRecord(fieldValue[j]);
                            }
                        }
                    }
    
                    //this.logWarn("validating value: " + fieldValue +
                    //             " of field: " + this.echo(field));
                    result[fieldName] = schema.validateFieldValue(field, fieldValue);
                }
            }
    
            if (schema.dropExtraFields) return result;
    
    
            for (var i = 0; i < fieldNames.length; i++) {
                var fieldName = fieldNames[i];
                record[fieldName] = result[fieldName]
            }
            return record;
        }

    #2
    This is to let you know that we have just incorporated your change to our codebase, you'll find it in the next nightly build. Thank you for your contribution.

    Comment

    Working...
    X