Uploaded image for project: 'Apache Avro'
  1. Apache Avro
  2. AVRO-1273

JavaScript dynamic generation of constructor funcs for Avro records

    XMLWordPrintableJSON

Details

    • Improvement
    • Status: Open
    • Minor
    • Resolution: Unresolved
    • None
    • None
    • javascript

    Description

      Per https://issues.apache.org/jira/browse/AVRO-485, I have extended Avro's JavaScript support to dynamically generate constructors for Avro records.

      Validation of JS objects against Avro schemas is still supported, but the API is different: Avro.validate(schema, obj) instead of Validator.validate(schema, obj). This is a breaking change but may be worth it because there are now several Avro.* funcs.

      Code is at https://github.com/sqs/avro/tree/lang-js/lang/js. I will attach a diff.

      Here is sample usage. We compile a ManyFieldsRecord constructor function using the Avro schema as input. The constructor function accepts a JS object, which it validates against the Avro schema and then uses to populate the new object's fields. Then ManyFieldRecords objects use Object.defineProperty setters to ensure that the object remains valid Avro.

      var manyFieldsRecordSchema = {
        type: 'record', name: 'ManyFieldsRecord', fields: [
          {name: 'nullField', type: 'null'},
          {name: 'booleanField', type: 'boolean'},
          {name: 'intField', type: 'int'},
          {name: 'longField', type: 'long'},
          {name: 'floatField', type: 'float'},
          {name: 'doubleField', type: 'double'},
          {name: 'stringField', type: 'string'},
          {name: 'bytesField', type: 'bytes'}
        ]
      };
      
      var compiledTypes = Avro.compile(manyFieldsRecordSchema)
        ManyFieldsRecord = compiledTypes.ManyFieldsRecord,
        mfr = new ManyFieldsRecord();
      
      test.throws(function() { mfr.nullField = undefined; });
      test.throws(function() { mfr.nullField = 1; });
      test.throws(function() { mfr.booleanField = 'a'; });
      test.throws(function() { mfr.intField = 'a'; }); // TODO: warn if setting int/long field to a non-integer
      test.throws(function() { mfr.longField = 'a'; });
      test.throws(function() { mfr.floatField = 'a'; });
      test.throws(function() { mfr.doubleField = 'a'; });
      test.throws(function() { mfr.stringField = 3; });
      
      mfr.nullField = null;
      mfr.booleanField = true;
      mfr.intField = 1;
      mfr.longField = 2;
      mfr.floatField = 3.5;
      mfr.doubleField = 4.5;
      mfr.stringField = 'a';
      test.equal(mfr.nullField, null);
      test.equal(mfr.booleanField, true);
      test.equal(mfr.intField, 1);
      test.equal(mfr.longField, 2);
      test.equal(mfr.floatField, 3.5);
      test.equal(mfr.doubleField, 4.5);
      test.equal(mfr.stringField, 'a');
      
      // Standard JavaScript JSON API interface:
      mgr.toJSON(); // --> returns plain JS object (without Avro-validating setters)
      JSON.stringify(mfr); // --> returns Avro JSON
      

      More examples are in the test dir: https://github.com/sqs/avro/tree/lang-js/lang/js/test.

      This is still rough and I am very interested in getting feedback. Thanks!

      Attachments

        1. AVRO-1273.patch
          92 kB
          Quinn Slack

        Activity

          People

            Unassigned Unassigned
            sqs Quinn Slack
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated: