Skip to content

Commit

Permalink
(FEAT) Add function parsepson
Browse files Browse the repository at this point in the history
This commit adds a new function to parse PSON formatted JSON.
This functionality was formally covered by `parsejson` which, despite its name, defaulted to PSON.
However this has been changed so that the function now accurately uses JSON, with this function being added to cover the potential need for PSON too specifically be used.
  • Loading branch information
david22swan committed Jul 26, 2022
1 parent 1306ed5 commit f74a389
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 0 deletions.
46 changes: 46 additions & 0 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ true boolean.
Puppet structure
* [`parsejson`](#parsejson): This function accepts JSON as a string and converts it into the correct
Puppet structure.
* [`parsepson`](#parsepson): This function accepts PSON, a Puppet variant of JSON, as a string and
converts it into the correct Puppet structure.
* [`parseyaml`](#parseyaml): This function accepts YAML as a string and converts it into the correct
Puppet structure.
* [`pick`](#pick): This function will return
Expand Down Expand Up @@ -3939,6 +3941,50 @@ Type: Ruby 3.x API
The optional second argument can be used to pass a default value that will
be returned if the parsing of YAML string have failed.

### <a name="parsehocon"></a>`parsehocon`

Type: Ruby 4.x API

This function accepts HOCON as a string and converts it into the correct
Puppet structure

#### Examples

##### How to parse hocon

```puppet
$data = parsehocon("{any valid hocon: string}")
```

#### `parsepson(String $pson_string, Optional[Any] $default)`

The parseson function.

Returns: `Data`

##### Examples

###### How to parse pson

```puppet
$data = parsepson('{"a":"1","b":"2"}')
```

For more information on PSON please see the following link:
https://puppet.com/docs/puppet/7/http_api/pson.html

##### `pson_string`

Data type: `String[1]`

A valid PSON string

##### `default`

Data type: `Optional[Any]`

An optional default to return if parsing the pson_string fails

#### `parseyaml()`

> *Note:*
Expand Down
29 changes: 29 additions & 0 deletions lib/puppet/functions/parsepson.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# frozen_string_literal: true

# @summary
# This function accepts PSON, a Puppet variant of JSON, as a string and converts
# it into the correct Puppet structure
#
# @example How to parse pson
# $data = parsepson('{"a":"1","b":"2"}')
#
# For more information on PSON please see the following link:
# https://puppet.com/docs/puppet/7/http_api/pson.html
#
Puppet::Functions.create_function(:parsepson) do
# @param pson_string A valid PSON string
# @param default An optional default to return if parsing the pson_string fails
# @return [Data]
dispatch :parsepson do
param 'String[1]', :pson_string
optional_param 'Any', :default
end

def parsepson(pson_string, default = :no_default_provided)
PSON.load(pson_string)
rescue StandardError => err
Puppet.debug("Parsing PSON failed with error: #{err.message}")
raise err if default == :no_default_provided
default
end
end
68 changes: 68 additions & 0 deletions spec/functions/parsepson_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# frozen_string_literal: true

require 'spec_helper'

describe 'parsepson' do
it 'exists' do
is_expected.not_to eq(nil)
end

it 'raises an error if called without any arguments' do
is_expected.to run.with_params
.and_raise_error(%r{wrong number of arguments}i)
end

context 'with correct PSON data' do
it 'is able to parse PSON data with a Hash' do
is_expected.to run.with_params('{"a":"1","b":"2"}')
.and_return('a' => '1', 'b' => '2')
end

it 'is able to parse PSON data with an Array' do
is_expected.to run.with_params('["a","b","c"]')
.and_return(['a', 'b', 'c'])
end

it 'is able to parse empty PSON values' do
actual_array = ['[]', '{}']
expected = [[], {}]
actual_array.each_with_index do |actual, index|
is_expected.to run.with_params(actual).and_return(expected[index])
end
end

it 'is able to parse PSON data with a mixed structure' do
is_expected.to run.with_params('{"a":"1","b":2,"c":{"d":[true,false]}}')
.and_return('a' => '1', 'b' => 2, 'c' => { 'd' => [true, false] })
end

it 'is able to parse PSON data with a UTF8 and double byte characters' do
is_expected.to run.with_params('{"×":"これ","ý":"記号","です":{"©":["Á","ß"]}}')
.and_return('×' => 'これ', 'ý' => '記号', 'です' => { '©' => ['Á', 'ß'] })
end

it 'does not return the default value if the data was parsed correctly' do
is_expected.to run.with_params('{"a":"1"}', 'default_value')
.and_return('a' => '1')
end
end

context 'with incorrect PSON data' do
it 'raises an error with invalid PSON and no default' do
is_expected.to run.with_params('')
.and_raise_error(PSON::ParserError)
end

it 'supports a structure for a default value' do
is_expected.to run.with_params('', 'a' => '1')
.and_return('a' => '1')
end

['', 1, 1.2, nil, true, false, [], {}, :yaml].each do |value|
it "returns the default value for an incorrect #{value.inspect} (#{value.class}) parameter" do
is_expected.to run.with_params(value, 'default_value')
.and_return('default_value')
end
end
end
end

0 comments on commit f74a389

Please sign in to comment.