Infer
NAME
JSON::Infer - Infer Raku Classes from JSON objects
SYNOPSIS
# Use the script to do it simply:
# Create the modules in the directory "foo"
raku-json-infer --uri=http://api.mixcloud.com/spartacus/party-time/ --out-dir=foo --class-name=Mixcloud::Show
# Or do it in your own code:
use JSON::Infer;
my $obj = JSON::Infer.new()
my $ret = $obj.infer(uri => 'http://api.mixcloud.com/spartacus/party-time/', class-name => 'Mixcloud::Show');
say $ret.make-class; # Print the class definition
DESCRIPTION
JSON is nearly ubiquitous on the internet, developers love it for making APIs. However the webservices that use it for transfer of data rarely have a machine readable specification that can be turned into code so developers who want to consume these services usually have to make the client definition themselves.
This module aims to provide a way to generate Raku classes that can represent the data from a JSON source. The structure and the types of the data is inferred from a single data item so the accuracy may depend on the consistency of the data.
METHODS
infer
multi method infer(Str:D :$uri!, Str :$class-name = 'My::JSON', Bool :$kebab = False) returns Class
multi method infer(Str:D :$file!, :$class-name = 'My::JSON', Bool :$kebab = False) returns Class
multi method infer(IO::Path:D :$file!, :$class-name = 'My::JSON', Bool :$kebab = False) returns Class
multi method infer(Str:D :$json!, Str :$class-name = 'My::JSON', Bool :$kebab = False) returns Class
This accepts a single path and returns a JSON::Infer::Class object, if there is an error retrieving the data or parsing the response it will throw an exception.
It requires the following named arguments:
uri
This is the uri that will be used to retrieve the content. It will need to be some protocol scheme that is understood by HTTP::UserAgent. This is required.
class-name
This is the name that will be used for the generated class, any child
classes that are discovered will parsing the attributes will have a name
based on this and the name of the attribute. If it is not supplied the
default is My::JSON
will be used.
kebab
If this is provided then the names of the attributes will be turned into the more popular Raku style with underscores replaced with hyphens.
ua
The HTTP::UserAgent object that will be used.
headers
Returns the default set of headers that will be applied to the HTTP::UserAgent object.
content-type
This is the content type that we want to use. The default is "application/json".
JSON::Infer::Class
This holds the infered definition of a class to be generated from JSON input.
attribute name
This is the name of the class.
attribute attributes
This is a Hash of the JSON::Infer::Attribute discovered in the object keyed by the name of the attribute.
attribute top-level
This is a Bool that indicates whether the class is the first one
encountered. It will be set by infer
method of JSON::Infer on
the class that it will return.
This is used internally by make-class
to determine whether it should
add any preamble that might be required.
method new-from-data
multi method new-from-data(:$class-name, :$content, :kebab) returns JSON::Infer::Class
multi method new-from-data(Str $name, $data, :kebab ) returns JSON::Infer::Class
This returns a JSON::Infer::Class constructed from the provided
reference. If the adverb kebab
is provided then this will be
applied to the attributes, causing the names to be adjusted accordingly.
method populate-from-data
method populate-from-data(JSON::Class:D: $datum)
This performs the actual inference from a single record.
method new-attribute
method new-attribute(Str $name, $value) returns JSON::Infer::Attribute
This creates a new attribute with the supplied name and its type infered
from the supplied $value
and adds it to the class, returning the
new JSON::Infer::Attribute.
method add-attribute
method add-attribute(JSON::Infer::Attribute $attr)
Add the attribute to this class, along with any classes that may have been discovered
method make-class
multi method make-class(Int $level = 0) returns Str
This returns the string representation of the class that has been
constructed. The argument $level
indicates the depth within the
nested structure and controls the indentation.
method file-path
method file-path() returns Str
This creates the suggested file path that can be used to save the output
of make-class
.
JSON::Infer::Attribute
A description of an infered attribute
new-from-value
This is an alternate constructor that will return a new object based on the name and attributes infered from the valie.
The third argument is the name of the class the attribute was found in this will be used to generate the names of any new classes found.
If the adverb kebab
is provided then the name of the attribute will
be adjusted to be in the more popular style with hyphens instead of
underscores.
infer-from-value
This does the actual work of infering the type from the value provided.
process-object
This is used to process an object value returning the JSON::Infer::Class object.
name
The name of the attribute as found in the JSON data.
raku-name
The rules for what a valid Raku identifier can be are more restrictive than those for JSON attribute names (which can be nearly any string,) this returns a sanitised version of the JSON name to be used when generating Perl code.
has-alternate-name
This is a Bool to indicate whether name
and raku-name
differ.
This is used internally when generating a string repreesentation of the
attribute to determine whether the json-name
trait is required.
type-constraint
The infered type constraint name.
class
Name of the class that this was being constructed for.
child-class-name
Returns the name of a class that will be used for an object type based on this attribute.
is-array
A Bool to indicate whether the attribute is an array or not.
sigil
This returns the sigil that should be used for the attribute (e.g '$', '@')
make-attribute
This returns a suitable string representation of the attribute for Raku.