lib/rdf/json/reader.rb in rdf-json-0.0.2 vs lib/rdf/json/reader.rb in rdf-json-0.1.0
- old
+ new
@@ -2,32 +2,128 @@
##
# RDF/JSON parser.
#
# @example Obtaining an RDF/JSON reader class
# RDF::Reader.for(:json) #=> RDF::JSON::Reader
- # RDF::Reader.for("spec/data/test.json")
- # RDF::Reader.for(:file_name => "spec/data/test.json")
+ # RDF::Reader.for("etc/doap.json")
+ # RDF::Reader.for(:file_name => "etc/doap.json")
# RDF::Reader.for(:file_extension => "json")
# RDF::Reader.for(:content_type => "application/json")
#
# @example Parsing RDF statements from an RDF/JSON file
- # RDF::JSON::Reader.open("spec/data/test.json") do |reader|
+ # RDF::JSON::Reader.open("etc/doap.json") do |reader|
# reader.each_statement do |statement|
# puts statement.inspect
# end
# end
#
# @example Parsing RDF statements from an RDF/JSON string
- # data = StringIO.new(File.read("spec/data/test.json"))
+ # data = StringIO.new(File.read("etc/doap.json"))
# RDF::JSON::Reader.new(data) do |reader|
# reader.each_statement do |statement|
# puts statement.inspect
# end
# end
#
# @see http://n2.talis.com/wiki/RDF_JSON_Specification
class Reader < RDF::Reader
format RDF::JSON::Format
- # TODO
+ ##
+ # @return [RDF::Graph]
+ attr_reader :graph
+
+ ##
+ # Initializes the RDF/JSON reader instance.
+ #
+ # @param [IO, File, String] input
+ # @param [Hash{Symbol => Object}] options
+ # @yield [reader]
+ # @yieldparam [Reader] reader
+ def initialize(input = $stdin, options = {}, &block)
+ super do
+ @graph = RDF::Graph.new
+
+ JSON.parse(@input.read).each do |subject, predicates|
+ subject = parse_subject(subject)
+ predicates.each do |predicate, objects|
+ predicate = parse_predicate(predicate)
+ objects.each do |object|
+ object = parse_object(object)
+ @graph << [subject, predicate, object]
+ end
+ end
+ end
+
+ block.call(self) if block_given?
+ end
+ end
+
+ ##
+ # Parses an RDF/JSON subject string into a URI reference or blank node.
+ #
+ # @param [String] subject
+ # @return [RDF::Resource]
+ def parse_subject(subject)
+ case subject
+ when /^_:/ then RDF::Node.new(subject[2..-1])
+ else RDF::URI.new(subject)
+ end
+ end
+
+ ##
+ # Parses an RDF/JSON predicate string into a URI reference.
+ #
+ # @param [String] predicate
+ # @return [RDF::URI]
+ def parse_predicate(predicate)
+ # TODO: support for CURIE predicates (issue #1 on GitHub).
+ parse_subject(predicate)
+ end
+
+ ##
+ # Parses an RDF/JSON object string into an RDF value.
+ #
+ # @param [Hash{String => Object}] object
+ # @return [RDF::Value]
+ def parse_object(object)
+ raise RDF::ReaderError.new, "missing 'type' key in #{object.inspect}" unless object.has_key?('type')
+ raise RDF::ReaderError.new, "missing 'value' key in #{object.inspect}" unless object.has_key?('value')
+
+ case type = object['type']
+ when 'bnode'
+ RDF::Node.new(object['value'][2..-1])
+ when 'uri'
+ RDF::URI.new(object['value'])
+ when 'literal'
+ RDF::Literal.new(object['value'], {
+ :language => object['lang'],
+ :datatype => object['datatype'],
+ })
+ else
+ raise RDF::ReaderError, "expected 'type' to be 'bnode', 'uri', or 'literal', but got #{type.inspect}"
+ end
+ end
+
+ ##
+ # Iterates the given block for each RDF statement in the input.
+ #
+ # @yield [statement]
+ # @yieldparam [RDF::Statement] statement
+ # @return [void]
+ def each_statement(&block)
+ @graph.each_statement(&block)
+ end
+
+ ##
+ # Iterates the given block for each RDF triple in the input.
+ #
+ # @yield [subject, predicate, object]
+ # @yieldparam [RDF::Resource] subject
+ # @yieldparam [RDF::URI] predicate
+ # @yieldparam [RDF::Value] object
+ # @return [void]
+ def each_triple(&block)
+ @graph.each_triple(&block)
+ end
end # class Reader
end # module RDF::JSON