lib/diaspora_federation/parsers/json_parser.rb
# frozen_string_literal: true
module DiasporaFederation
module Parsers
# This is a parser of JSON serialized object. JSON object format is defined by
# JSON schema which is available at https://diaspora.github.io/diaspora_federation/schemas/federation_entities.json.
# TODO: We must publish the schema at a real URL
class JsonParser < BaseParser
# @see BaseParser#parse
# @param [Hash] json_hash A hash acquired by running JSON.parse with JSON serialized entity
# @return [Array[1]] comprehensive data for an entity instantiation
def parse(json_hash)
from_json_sanity_validation(json_hash)
parse_entity_data(json_hash["entity_data"])
end
private
def parse_entity_data(entity_data)
hash = entity_data.to_h {|key, value|
property = entity_type.class_props.keys.find {|name| name.to_s == key }
if property
type = entity_type.class_props[property]
[property, parse_element_from_value(type, entity_data[key])]
else
[key, value]
end
}
[hash]
end
def parse_element_from_value(type, value)
return if value.nil?
if %i[integer boolean timestamp].include?(type) && !value.is_a?(String)
value
elsif type.instance_of?(Symbol)
parse_string(type, value)
elsif type.instance_of?(Array)
raise DeserializationError, "Expected array for #{type}" unless value.respond_to?(:map)
value.map {|element|
type.first.from_json(element)
}
elsif type.ancestors.include?(Entity)
type.from_json(value)
end
end
def from_json_sanity_validation(json_hash)
missing = %w[entity_type entity_data].select {|prop| json_hash[prop].nil? }.join(", ")
raise DeserializationError, "Required properties are missing in JSON object: #{missing}" unless missing.empty?
assert_parsability_of(json_hash["entity_type"])
end
# Raised when the format of the input JSON data doesn't match the parser's expectations
class DeserializationError < RuntimeError
end
end
end
end