YAML_PARSE

The YAML_PARSE function takes a YAML (YAML Ain't Markup Language) string or file and converts it into an IDL variable.

This routine is written in the IDL language. Its source code can be found in the file yaml_parse.pro in the lib/datatypes subdirectory of the IDL distribution.

Tip: The result of YAML_PARSE is a nested hierarchy of YAML objects, arrays, and scalar values. If you print out the result, the output will automatically be printed in YAML format.

Examples

Convert a YAML stream into a nested set of IDL YAML objects:

IDL> yaml = `MyYaml:\n key1: text1\n key2: [1, cat, 2.5]`

IDL> result = yaml_parse(yaml)

IDL> help, result

RESULT YAML_MAP <ID=1 NELEMENTS=1>

IDL> print, result

MyYaml:

key1: text1

key2:

- 1

- cat

- 2.5

IDL> help, result['MyYaml']

<Expression> YAML_MAP <ID=2 NELEMENTS=2>

IDL> help, result['MyYaml','key2']

<Expression> YAML_SEQUENCE <ID=3 NELEMENTS=3>

Syntax

Result = YAML_PARSE(String, /PRESERVE_ALIAS )

Return Value

The result is a nested hierarchy of YAML objects, IDL arrays, and IDL scalar values. See below for the rules on converting YAML data into IDL datatypes.

Arguments

String

String must be a scalar string or string array containing a valid YAML stream.

String can also be a file name. In this case the entire file is read into memory and parsed as a single YAML string.

Keywords

PRESERVE_ALIAS

By default, YAML_PARSE automatically resolves all YAML aliases from their corresponding anchors and returns the resulting values, including any value overrides. If PRESERVE_ALIAS is set then the result will contain the original, unmodified aliases as YAML_Value and YAML_Alias objects. For example, here we have an anchor for a "planet" mapping. The "Earth" key is just a direct alias, while the "Jupiter" key overrides one of the mapping keys:

yaml = `

default: &planet

type: terrestrial

Earth: *planet

Jupiter:

<<: *planet

type: gas giant`

print, yaml_parse(yaml) ; resolve all aliases

IDL prints:

default:

type: terrestrial

Earth:

type: terrestrial

Jupiter:

type: gas giant

Now print the YAML but keep the aliases using the PRESERVE_ALIAS keyword:

print, yaml_parse(yaml, /preserve_alias)

IDL prints:

default: &planet

type: terrestrial

Earth: *planet

Jupiter:

<<: *planet

type: gas giant

Conversion Rules

When converting YAML streams into IDL variables, the following rules are used:

YAML Item IDL Variable Type Notes
Multiple Documents YAML_Multidoc

Optional COMMENTS, GLOBAL_TAGS

A single document with a mapping YAML_Stream_Map

Optional COMMENTS, GLOBAL_TAGS

A single document with a sequence

YAML_Stream_Sequence

Optional COMMENTS, GLOBAL_TAGS

Mapping YAML_Map

Optional ANCHOR, TAG properties

!!set YAML_Map Mapping of keys with !NULL values
Sequence of mixed types YAML_Sequence

Optional ANCHOR, TAG properties

Sequence of same types1 Array

Boolean, LONG64, DOUBLE, DCOMPLEX

!!omap YAML_Sequence Sequence of YAML_Maps
Scalar value with unknown tag3 YAML_Value TAG and VALUE properties
Scalar value with an anchor2 YAML_Value

ANCHOR, VALUE properties, optional TAG

Alias (reference) YAML_Alias ALIAS property
Quoted string String  
~, null, Null, NULL !NULL  

false, False, FALSE, true, True, TRUE

Boolean  
Integer from –263 to 263–1 LONG64  
Integers larger than +/–263 BigInteger  
Floating-point number DOUBLE  
!!binary with base64 Byte array  

!!python/complex or complex of form A+Bj

DCOMPLEX  
tag:stsci.edu:asdf/core/complex-1.0.0 DCOMPLEX ASDF file format

1A sequence with both integers and floating-point values will be returned as an IDL array of type DOUBLE.

2A YAML scalar with an anchor will be returned as a YAML_Value object. The VALUE property will contain the scalar value as a string, and will not be converted to one of the other scalar types.

3A YAML scalar with an unknown tag will be returned as a YAML_Value object. The VALUE property will contain the scalar value as a string, and will not be converted to one of the other scalar types.

Conformance

In general, YAML_PARSE and YAML_SERIALIZE conform to the YAML 1.2 standard, with the following specific notes:

Some exceptions to the conformance:

Additional Examples

Parsing a YAML File

First we parse a sample YAML file into YAML objects:

yaml = [ $

'Product: IDL', $

'Year: 1977', $

'Creator: David Stern', $

'Datatypes: [boolean, long, float, string]', $

'Examples: [true, 1234, 3.14, "hello"]', $

'Functions:', $

' - FFT:', $

'   Arguments: [{Name: InputArray, Type: float}]', $

'   Keywords: [{Name: Double, Type: boolean}]']

yp = yaml_parse(yaml)

We can use help and print to examine the contents:

help, yp

print, (yp.keys()).toArray()

IDL prints:

YP YAML_MAP <ID=3 NELEMENTS=6>

Product Year Creator Datatypes Examples Functions

We can use array indexing to drill down into the returned objects:

help, yp['Datatypes']

help, yp['Examples']

help, yp['Functions', 0, 'FFT', 'Arguments', 0, 'Name']

IDL prints:

<Expression> STRING = Array[4]

<Expression> YAML_SEQUENCE <ID=5 NELEMENTS=4>

<Expression> STRING = 'InputArray'

Convert to JSON

If the YAML file contains simple YAML_Map, YAML_Sequence, arrays, and scalars, then you can directly convert the YAML_PARSE output to JSON:

IDL> print, json_serialize(yp)

{"Product":"IDL","Year":1977,"Creator":"David Stern","Datatypes":["boolean","long","float","string"],"Examples":[true,1234,3.1400000000000001,"hello"],"Functions":[{"FFT":{"Arguments":[{"Name":"InputArray","Type":"float"}],"Keywords":[{"Name":"Double","Type":"boolean"}]}}]}

This will not work for YAML files that contain streams or special TAG values.

Create YAML Streams

You can construct YAML output from regular IDL arrays, scalars, hashes, or lists. More complex YAML files can be created using the YAML object classes such as YAML_Multidoc, YAML_Stream_Map, YAML_Stream_Sequence, YAML_Map, or YAML_Sequence. These classes allow you to add YAML comments, global tags, anchors, and tags.

For our simple example above, we can recreate the YAML by just using regular IDL variables:

h = OrderedHash()

h['Product'] = 'IDL'

h['Year'] = 1977

h['Creator'] = 'David Stern'

h['Datatypes'] = ["boolean","long","float","string"]

h['Examples'] = List(!true, 1234, 3.14d, "hello")

args = [Hash('Name', 'InputArray', 'Type', 'float')]

kw = [Hash('Name', 'Double', 'Type', 'boolean')]

fn1 = Hash('FFT', Hash('Arguments', args, 'Keywords', kw))

h['Functions'] = List(fn1)

print, yaml_serialize(h)

This will produce essentially the same YAML stream as in the beginning, although some of the YAML mappings and sequences will be written out in "block" format rather than the shorter "flow" style. Both forms are equivalent.

Version History

8.9

Introduced

See Also

YAML_Alias, YAML_Map, YAML_Sequence, YAML_Multidoc, YAML_Stream_Map, YAML_Stream_Sequence, YAML_Value, YAML_SERIALIZE