<commit_before>require "jsoning/version"

require "jsoning/dsl/for_dsl"
require "jsoning/exceptions/error"
require "jsoning/foundations/mapper"
require "jsoning/foundations/protocol"

require "json"

module Jsoning
  PROTOCOLS = {}
  # if type is defined here, we will use it to extract its value for the key
  TYPE_EXTENSIONS = {}

  module_function

  # returns a protocol, or create one if none exists
  def protocol_for(klass)
    protocol = PROTOCOLS[klass.to_s]
    if protocol.nil?
      protocol = Jsoning::Protocol.new(klass)
      PROTOCOLS[klass.to_s] = protocol
    end
    protocol
  end

  # retrieve the protocol or raise an error when the protocol is not defined yet
  def protocol_for!(klass)
    protocol = PROTOCOLS[klass.to_s]
    raise Jsoning::Error, "Undefined Jsoning protocol for #{klass.to_s}" if protocol.nil?
    protocol
  end

  # clearing the protocols
  def clear
    PROTOCOLS.clear
  end

  # define the protocol
  def for(klass, &block)
    Jsoning::ForDsl.new(protocol_for(klass)).instance_eval(&block)
  end

  # generate the json document
  def generate(object, options = {})
    initialize_type_extensions 
    protocol = protocol_for!(object.class)
    protocol.generate(object, options)
  end

  @@type_extension_initialized = false
  def initialize_type_extensions
    @@type_extension_initialized = true if !!@@type_extension_initialized
    return if @@type_extension_initialized

    begin
      require "time"
      ::Time
      self.add_type Time, processor: proc { |time| time.iso8601 }
    rescue
    end

    begin
      # try to define value extractor for ActiveSupport::TimeWithZone which is in common use
      # for AR model
      ::ActiveSupport::TimeWithZone
      self.add_type ActiveSupport::TimeWithZone, processor: proc { |time| time.send(:iso8601) }
    rescue 
      # nothing, don't add
    end

    begin
      ::DateTime
      self.add_type DateTime, processor: proc { |date| date.send(:iso8601) }
    rescue => e 
      # nothing, don't add
    end

    begin
      ::Date
      self.add_type Date, processor: proc { |date| date.send(:iso8601) }
    rescue 
      # nothing, don't add
    end
  end

  def [](object) 
    protocol = protocol_for!(object.class)
    protocol.retrieve_values_from(object)
  end

  def add_type(klass, options = {})
    processor = options[:processor]
    raise Jsoning::Error, "Pass in processor that is a proc explaining how to extract the value" unless processor.is_a?(Proc)
    TYPE_EXTENSIONS[klass.to_s] = processor
    nil
  end

  # monkey patch Kernel
  module ::Kernel
    private

    def Jsoning(object, options = {})
      Jsoning.generate(object, options)
    end
  end

  # parse the JSON String to Hash
  def parse(json_string, klass)
    protocol = protocol_for!(klass)
    protocol.construct_hash_from(json_string)
  end
end<commit_msg>converting to hash also need to define common interpreter<commit_after>require "jsoning/version"

require "jsoning/dsl/for_dsl"
require "jsoning/exceptions/error"
require "jsoning/foundations/mapper"
require "jsoning/foundations/protocol"

require "json"

module Jsoning
  PROTOCOLS = {}
  # if type is defined here, we will use it to extract its value for the key
  TYPE_EXTENSIONS = {}

  module_function

  # returns a protocol, or create one if none exists
  def protocol_for(klass)
    protocol = PROTOCOLS[klass.to_s]
    if protocol.nil?
      protocol = Jsoning::Protocol.new(klass)
      PROTOCOLS[klass.to_s] = protocol
    end
    protocol
  end

  # retrieve the protocol or raise an error when the protocol is not defined yet
  def protocol_for!(klass)
    protocol = PROTOCOLS[klass.to_s]
    raise Jsoning::Error, "Undefined Jsoning protocol for #{klass.to_s}" if protocol.nil?
    protocol
  end

  # clearing the protocols
  def clear
    PROTOCOLS.clear
  end

  # define the protocol
  def for(klass, &block)
    Jsoning::ForDsl.new(protocol_for(klass)).instance_eval(&block)
  end

  # generate the json document
  def generate(object, options = {})
    protocol = protocol_for!(object.class)
    protocol.generate(object, options)
  end

  @@type_extension_initialized = false
  # define value extractor/interpreter for commonly used ruby datatypes that are not
  # part of standard types supported by JSON
  def initialize_type_extensions
    @@type_extension_initialized = true if !!@@type_extension_initialized
    return if @@type_extension_initialized

    begin
      require "time"
      ::Time
      self.add_type Time, processor: proc { |time| time.iso8601 }
    rescue
    end

    begin
      # try to define value extractor for ActiveSupport::TimeWithZone which is in common use
      # for AR model
      ::ActiveSupport::TimeWithZone
      self.add_type ActiveSupport::TimeWithZone, processor: proc { |time| time.send(:iso8601) }
    rescue 
      # nothing, don't add
    end

    begin
      ::DateTime
      self.add_type DateTime, processor: proc { |date| date.send(:iso8601) }
    rescue => e 
      # nothing, don't add
    end

    begin
      ::Date
      self.add_type Date, processor: proc { |date| date.send(:iso8601) }
    rescue 
      # nothing, don't add
    end
  end

  def [](object) 
    Jsoning.initialize_type_extensions 
    protocol = protocol_for!(object.class)
    protocol.retrieve_values_from(object)
  end

  def add_type(klass, options = {})
    processor = options[:processor]
    raise Jsoning::Error, "Pass in processor that is a proc explaining how to extract the value" unless processor.is_a?(Proc)
    TYPE_EXTENSIONS[klass.to_s] = processor
    nil
  end

  # monkey patch Kernel
  module ::Kernel
    private

    def Jsoning(object, options = {})
      Jsoning.initialize_type_extensions 
      Jsoning.generate(object, options)
    end
  end

  # parse the JSON String to Hash
  def parse(json_string, klass)
    Jsoning.initialize_type_extensions 
    protocol = protocol_for!(klass)
    protocol.construct_hash_from(json_string)
  end
end
{'fraction_non_alphanumeric': 0.08350100603621731, 'fraction_numerical': 0.0053655264922870555, 'mean_word_length': 3.3193338160753076, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, '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': '3460669', 'n_tokens_mistral': 1850, 'n_tokens_neox': 1822, 'n_words': 527}