module HCL::Serializable

Overview

The HCL::Serializable module automatically generates methods for HCL serialization and deserialization when included.

Example

require "hcl"

class Location
  include HCL::Serializable

  @[HCL::Attribute(key: "lat")]
  property latitude : Float64

  @[HCL::Attribute(key: "lng")]
  property longitude : Float64
end

class House
  include HCL::Serializable

  @[HCL::Attribute]
  property address : String

  @[HCL::Block]
  property location : Location?
end

hcl_house = <<-HCL
  address = "Crystal Road 1234"
  location {
    lat = 12.3
    lng = 34.5
  }

HCL
house = House.from_hcl(hcl_house)
house.address  # => "Crystal Road 1234"
house.location # => #<Location:0x10cd93d80 @latitude=12.3, @longitude=34.5>
house.to_hcl  # => "
  address = \"Crystal Road 1234\"

  location {
    lat = 12.3
    lng = 34.5
  }
"

Usage

Including HCL::Serializable will create #to_hcl and self.from_hcl methods on the current class, and a constructor which takes an HCL::AST::Body and an HCL::ExpressionContext. By default, these methods serialize into an HCL document containing the value of every tagged instance variable, the keys being the instance variable name. Most primitives and collections supported as instance variable values (string, integer, array, hash, etc.), along with objects which define #to_hcl(builder : HCL::Builder).

Union types are supported for attributes and blocks, including unions with Nil. If multiple types in a union parse correctly, it is undefined which one will be chosen.

To denote an individual instance variable to be parsed and serialized, the annotation HCL::Attribute must be placed on the instance variable. Annotating property, getter and setter macros is also allowed.

require "hcl"

class A
  include HCL::Serializable

  @[HCL::Attribute(key: "my_key", emit_null: true)]
  getter a : Int32?
end

HCL::Attribute properties:

Deserialization also respects default values of variables:

require "hcl"

struct A
  include HCL::Serializable

  @[HCL::Attribute]
  @a : Int64

  @[HCL::Attribute]
  @b : Float64 = 1.0
end

A.from_hcl("a = 1\n") # => A(@a=1, @b=1.0)

Extensions: HCL::Serializable::Strict and HCL::Serializable::Unmapped.

If the HCL::Serializable::Strict module is included, unknown properties in the HCL document will raise a parse exception. By default the unknown properties are silently ignored. If the HCL::Serializable::Unmapped module is included, unknown attributes and blocks in the HCL document will be stored in respective Hash(String, HCL::AST::Node). For blocks, any unmapped labels will be stored in a Hash(Int32, HCL::AST::Node), where the key is the label index. On serialization, any keys inside hcl_unmapped_attributes, hcl_unmapped_blocks, and hcl_unmapped_labels will be serialized and appended to the current HCL block or document. The deserialied values are AST nodes in order to allow for later evaluation, perhaps with a different expression context than the original document.

require "hcl"

struct A
  include HCL::Serializable
  include HCL::Serializable::Unmapped

  @[HCL::Attribute]
  @a : Int32
end

a = A.from_hcl("a = 1\nb = 2\n") # => A(@hcl_unmapped_attributes={"b" => HCL::AST::Number.new(2_i64)}, @a=1)
a.to_hcl                         # => "a = 1\nb = 2\n"

Class annotation HCL::Serializable::Options

supported properties:

require "hcl"

@[HCL::Serializable::Options(emit_nulls: true)]
class A
  include HCL::Serializable

  @[HCL::Serializable]
  @a : Int32?
end

This module is derived heavily from JSON::Serializable

Defined in:

hcl/serializable.cr

Constructors

Instance Method Summary

Constructor Detail

def self.new(*, __node_from_hcl : HCL::AST::Body, __ctx_from_hcl : HCL::ExpressionContext) #

[View source]

Instance Method Detail

def to_hcl(io : IO, node : AST::Node | Nil = AST::Document.new) #

Serializes HCL and writes it to the given IO as a string. Root node for building can be specified by node argument. Defaults to AST::Document.


[View source]
def to_hcl(builder : HCL::Builder) #

Appends passed in HCL::Builder with the HCL structure of the class/struct.

Returns the passed in HCL::Builder


[View source]
def to_hcl #

Returns HCL serialization as a String


[View source]