<commit_before>
Data.Codec = Ember.Object.extend({
  decode: function (value/*, qualifier*/) {
    return value;
  },

  encode: function (value/*, qualifier*/) {
    return value;
  }
});


Data.codec = {
  string: Data.Codec.create({
    decode: function (value) {
      if (Ember.isNone(value)) {
        return value;
      }
      switch (Ember.typeOf(value)) {
      case 'string':
        return value;
      case 'object':
        return JSON.stringify(value);
      default:
        Ember.Logger.warn('string codec returning raw %@ value:'.fmt(Ember.typeOf(value)), value);
        return value;
      }
    },

    encode: function (value/*, qualifier*/) {
      if (!Ember.isNone(value)) {
        return '%@'.fmt(value);
      }
      return null;
    }
  }),

  number: Data.Codec.create({
    decode: function (value/*, qualifier*/) {
      if (Ember.typeOf(value) === 'number') {
        return value;
      }
      return Number(value);
    }
  }),

  boolean: Data.Codec.create({
    encode: function (value/*, qualifier*/) {
      return value ? true: false;
    }
  }),

  array: Data.Codec.create({
    decode: function (value, qualifier) {
      if (value) {
        return value.map(function (item) {
          return Data.codec[qualifier].decode(item);
        });
      }
      return null;
    },

    encode: function (value, qualifier) {
      if (value) {
        return value.map(function (item) {
          return Data.codec[qualifier].encode(item);
        });
      }
    }
  }),

  date: Data.Codec.create({
    decode: function (value/*, qualifier*/) {
      if (Ember.typeOf(value) === 'date') {
        return moment(value);
      }
      return moment(value, 'YYYY-MM-DD');
    },

    encode: function (value/*, qualifier*/) {
      if (value) {
        return value.format('YYYY-MM-DD');
      }
      return null;
    }
  }),

  time: Data.Codec.create({
    decode: function (value/*, qualifier*/) {
      return moment(value, 'HH:mm');
    },

    encode: function (value/*, qualifier*/) {
      if (value) {
        return value.format('HH:mm');
      }
      return null;
    }
  }),

  datetime: Data.Codec.create({
    decode: function (value/*, qualifier*/) {
      return moment(value, 'YYYY-MM-DDTHH:mm:ssZ');
    },

    encode: function (value/*, qualifier*/) {
      if (value) {
        return value.format('YYYY-MM-DDTHH:mm:ssZ');
      }
      return null;
    }
  }),

  json: Data.Codec.create({
    decode: function (value/*, qualifier*/) {
      return JSON.stringify(value);
    },

    encode: function (value/*, qualifier*/) {
      if (value === undefined) {
        return undefined;
      }
      return JSON.parse(value);
    }
  })
};<commit_msg>Improve JSON attribute encoding: never break, even if JSON invalid<commit_after>
Data.Codec = Ember.Object.extend({
  decode: function (value/*, qualifier*/) {
    return value;
  },

  encode: function (value/*, qualifier*/) {
    return value;
  }
});


Data.codec = {
  string: Data.Codec.create({
    decode: function (value) {
      if (Ember.isNone(value)) {
        return value;
      }
      switch (Ember.typeOf(value)) {
      case 'string':
        return value;
      case 'object':
        return JSON.stringify(value);
      default:
        Ember.Logger.warn('string codec returning raw %@ value:'.fmt(Ember.typeOf(value)), value);
        return value;
      }
    },

    encode: function (value/*, qualifier*/) {
      if (!Ember.isNone(value)) {
        return '%@'.fmt(value);
      }
      return null;
    }
  }),

  number: Data.Codec.create({
    decode: function (value/*, qualifier*/) {
      if (Ember.typeOf(value) === 'number') {
        return value;
      }
      return Number(value);
    }
  }),

  boolean: Data.Codec.create({
    encode: function (value/*, qualifier*/) {
      return value ? true: false;
    }
  }),

  array: Data.Codec.create({
    decode: function (value, qualifier) {
      if (value) {
        return value.map(function (item) {
          return Data.codec[qualifier].decode(item);
        });
      }
      return null;
    },

    encode: function (value, qualifier) {
      if (value) {
        return value.map(function (item) {
          return Data.codec[qualifier].encode(item);
        });
      }
    }
  }),

  date: Data.Codec.create({
    decode: function (value/*, qualifier*/) {
      if (Ember.typeOf(value) === 'date') {
        return moment(value);
      }
      return moment(value, 'YYYY-MM-DD');
    },

    encode: function (value/*, qualifier*/) {
      if (value) {
        return value.format('YYYY-MM-DD');
      }
      return null;
    }
  }),

  time: Data.Codec.create({
    decode: function (value/*, qualifier*/) {
      return moment(value, 'HH:mm');
    },

    encode: function (value/*, qualifier*/) {
      if (value) {
        return value.format('HH:mm');
      }
      return null;
    }
  }),

  datetime: Data.Codec.create({
    decode: function (value/*, qualifier*/) {
      return moment(value, 'YYYY-MM-DDTHH:mm:ssZ');
    },

    encode: function (value/*, qualifier*/) {
      if (value) {
        return value.format('YYYY-MM-DDTHH:mm:ssZ');
      }
      return null;
    }
  }),

  json: Data.Codec.create({
    decode: function (value/*, qualifier*/) {
      return JSON.stringify(value);
    },

    encode: function (value/*, qualifier*/) {
      if (Ember.isBlank(value)) {
        return undefined;
      }
      try {
        return JSON.parse(value);
      } catch (e) {
        return null;
      }
    }
  })
};
{'fraction_non_alphanumeric': 0.1647122496842865, 'fraction_numerical': 0.0, 'mean_word_length': 2.066371681415929, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1790498', 'n_tokens_mistral': 1805, 'n_tokens_neox': 1789, 'n_words': 381}