lib/types.js
function stringify(obj, opts) {
  EXPORT_ATTRS = opts && opts.exportAttrs;
  var noDeref = opts && opts.noDeref;

  // Since JS objects are unordered, this implementation (unfortunately)
  // relies on engines returning properties in the same order that they are
  // inserted in. This is not in the JS spec, but can be "somewhat" safely
  // assumed (more here: http://stackoverflow.com/q/5525795/1062617).
  return (function (registry) {
    return JSON.stringify(obj, function (key, value) {
      if (value) {
        if (
          typeof value == 'object' &&
          value.hasOwnProperty('default') &&
          !value.hasOwnProperty('logicalType')
        ) {
          // This is a field.
          if (EXPORT_ATTRS) {
            return {
              name: value.name,
              type: value.type,
              'default': value['default'],
              order: value.order !== 'ascending' ? value.order : undefined,
              aliases: value.aliases.length ? value.aliases : undefined
            };
          } else {
            return {name: value.name, type: value.type};
          }
        } else if (value.aliases) {
          // This is a named type (enum, fixed, record, error).
          var name = value.name;
          if (name) {
            // If the type is anonymous, we always dereference it.
            if (noDeref || registry[name]) {
              return name;
            }
            registry[name] = true;
          }
          if (!EXPORT_ATTRS || !value.aliases.length) {
            value.aliases = undefined;
          }
        }
      }
      return value;
    });
  })({});
}
function stringify(obj, opts) {
  EXPORT_ATTRS = opts && opts.exportAttrs;
  var noDeref = opts && opts.noDeref;

  // Since JS objects are unordered, this implementation (unfortunately)
  // relies on engines returning properties in the same order that they are
  // inserted in. This is not in the JS spec, but can be "somewhat" safely
  // assumed (more here: http://stackoverflow.com/q/5525795/1062617).
  return (function (registry) {
    return JSON.stringify(obj, function (key, value) {
      if (value) {
        if (
          typeof value == 'object' &&
          value.hasOwnProperty('default') &&
          !value.hasOwnProperty('logicalType')
        ) {
          // This is a field.
          if (EXPORT_ATTRS) {
            return {
              name: value.name,
              type: value.type,
              'default': value['default'],
              order: value.order !== 'ascending' ? value.order : undefined,
              aliases: value.aliases.length ? value.aliases : undefined
            };
          } else {
            return {name: value.name, type: value.type};
          }
        } else if (value.aliases) {
          // This is a named type (enum, fixed, record, error).
          var name = value.name;
          if (name) {
            // If the type is anonymous, we always dereference it.
            if (noDeref || registry[name]) {
              return name;
            }
            registry[name] = true;
          }
          if (!EXPORT_ATTRS || !value.aliases.length) {
            value.aliases = undefined;
          }
        }
      }
      return value;
    });
  })({});
}
function stringify ( obj , opts ) { EXPORT_ATTRS = opts && opts . exportAttrs ; var noDeref = opts && opts . noDeref ; // Since JS objects are unordered, this implementation (unfortunately) // relies on engines returning properties in the same order that they are // inserted in. This is not in the JS spec, but can be "somewhat" safely // assumed (more here: http://stackoverflow.com/q/5525795/1062617). return ( function ( registry ) { return JSON . stringify ( obj , function ( key , value ) { if ( value ) { if ( typeof value == 'object' && value . hasOwnProperty ( 'default' ) && ! value . hasOwnProperty ( 'logicalType' ) ) { // This is a field. if ( EXPORT_ATTRS ) { return { name : value . name , type : value . type , 'default' : value [ 'default' ] , order : value . order !== 'ascending' ? value . order : undefined , aliases : value . aliases . length ? value . aliases : undefined } ; } else { return { name : value . name , type : value . type } ; } } else if ( value . aliases ) { // This is a named type (enum, fixed, record, error). var name = value . name ; if ( name ) { // If the type is anonymous, we always dereference it. if ( noDeref || registry [ name ] ) { return name ; } registry [ name ] = true ; } if ( ! EXPORT_ATTRS || ! value . aliases . length ) { value . aliases = undefined ; } } } return value ; } ) ; } ) ( { } ) ; }
Correctly stringify an object which contains types.

@param obj {Object} The object to stringify. Typically, a type itself or an
object containing types. Any types inside will be expanded only once then
referenced by name.
@param opts {Object} Options:
+ `exportAttrs` {Boolean} Include field and logical type attributes.
+ `noDeref` {Boolean} Always reference types by name when possible,
rather than expand it the first time it is encountered.
Correctly stringify an object which contains types .