Skip to content

Commit c3ad329

Browse files
committed
(FEAT) Add function parsepson
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.
1 parent 1306ed5 commit c3ad329

File tree

3 files changed

+146
-0
lines changed

3 files changed

+146
-0
lines changed

REFERENCE.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ true boolean.
140140
Puppet structure
141141
* [`parsejson`](#parsejson): This function accepts JSON as a string and converts it into the correct
142142
Puppet structure.
143+
* [`parsepson`](#parsepson): This function accepts PSON, a Puppet variant of JSON, as a string and
144+
converts it into the correct Puppet structure.
143145
* [`parseyaml`](#parseyaml): This function accepts YAML as a string and converts it into the correct
144146
Puppet structure.
145147
* [`pick`](#pick): This function will return
@@ -3939,6 +3941,50 @@ Type: Ruby 3.x API
39393941
The optional second argument can be used to pass a default value that will
39403942
be returned if the parsing of YAML string have failed.
39413943

3944+
### <a name="parsehocon"></a>`parsehocon`
3945+
3946+
Type: Ruby 4.x API
3947+
3948+
This function accepts HOCON as a string and converts it into the correct
3949+
Puppet structure
3950+
3951+
#### Examples
3952+
3953+
##### How to parse hocon
3954+
3955+
```puppet
3956+
$data = parsehocon("{any valid hocon: string}")
3957+
```
3958+
3959+
#### `parsepson(String $pson_string, Optional[Any] $default)`
3960+
3961+
The parseson function.
3962+
3963+
Returns: `Data`
3964+
3965+
##### Examples
3966+
3967+
###### How to parse pson
3968+
3969+
```puppet
3970+
$data = parsepson("{any valid pson: string}")
3971+
```
3972+
3973+
For more information on PSON please see the following link:
3974+
https://puppet.com/docs/puppet/7/http_api/pson.html
3975+
3976+
##### `pson_string`
3977+
3978+
Data type: `String`
3979+
3980+
A valid PSON string
3981+
3982+
##### `default`
3983+
3984+
Data type: `Optional[Any]`
3985+
3986+
An optional default to return if parsing the pson_string fails
3987+
39423988
#### `parseyaml()`
39433989

39443990
> *Note:*

lib/puppet/functions/parsepson.rb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# frozen_string_literal: true
2+
3+
#
4+
# parsepson.rb
5+
#
6+
# @summary
7+
# This function accepts PSON, a Puppet variant of JSON, as a string and converts
8+
# it into the correct Puppet structure
9+
#
10+
# @example How to parse pson
11+
# $data = parsepson("{any valid pson: string}")
12+
#
13+
# For more information on PSON please see the following link:
14+
# https://puppet.com/docs/puppet/7/http_api/pson.html
15+
#
16+
Puppet::Functions.create_function(:parsepson) do
17+
# @param pson_string A valid PSON string
18+
# @param default An optional default to return if parsing the pson_string fails
19+
# @return [Data]
20+
dispatch :parsepson do
21+
param 'String', :pson_string
22+
optional_param 'Any', :default
23+
end
24+
25+
def parsepson(pson_string, default = :no_default_provided)
26+
PSON.load(pson_string)
27+
rescue StandardError => err
28+
Puppet.debug("Parsing PSON failed with error: #{err.message}")
29+
raise err if default == :no_default_provided
30+
default
31+
end
32+
end

spec/functions/parsepson_spec.rb

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# frozen_string_literal: true
2+
3+
require 'spec_helper'
4+
5+
describe 'parsepson' do
6+
it 'exists' do
7+
is_expected.not_to eq(nil)
8+
end
9+
10+
it 'raises an error if called without any arguments' do
11+
is_expected.to run.with_params
12+
.and_raise_error(%r{wrong number of arguments}i)
13+
end
14+
15+
context 'with correct PSON data' do
16+
it 'is able to parse PSON data with a Hash' do
17+
is_expected.to run.with_params('{"a":"1","b":"2"}')
18+
.and_return('a' => '1', 'b' => '2')
19+
end
20+
21+
it 'is able to parse PSON data with an Array' do
22+
is_expected.to run.with_params('["a","b","c"]')
23+
.and_return(['a', 'b', 'c'])
24+
end
25+
26+
it 'is able to parse empty PSON values' do
27+
actual_array = ['[]', '{}']
28+
expected = [[], {}]
29+
actual_array.each_with_index do |actual, index|
30+
is_expected.to run.with_params(actual).and_return(expected[index])
31+
end
32+
end
33+
34+
it 'is able to parse PSON data with a mixed structure' do
35+
is_expected.to run.with_params('{"a":"1","b":2,"c":{"d":[true,false]}}')
36+
.and_return('a' => '1', 'b' => 2, 'c' => { 'd' => [true, false] })
37+
end
38+
39+
it 'is able to parse PSON data with a UTF8 and double byte characters' do
40+
is_expected.to run.with_params('{"×":"これ","ý":"記号","です":{"©":["Á","ß"]}}')
41+
.and_return('×' => 'これ', 'ý' => '記号', 'です' => { '©' => ['Á', 'ß'] })
42+
end
43+
44+
it 'does not return the default value if the data was parsed correctly' do
45+
is_expected.to run.with_params('{"a":"1"}', 'default_value')
46+
.and_return('a' => '1')
47+
end
48+
end
49+
50+
context 'with incorrect PSON data' do
51+
it 'raises an error with invalid PSON and no default' do
52+
is_expected.to run.with_params('')
53+
.and_raise_error(PSON::ParserError)
54+
end
55+
56+
it 'supports a structure for a default value' do
57+
is_expected.to run.with_params('', 'a' => '1')
58+
.and_return('a' => '1')
59+
end
60+
61+
['', 1, 1.2, nil, true, false, [], {}, :yaml].each do |value|
62+
it "returns the default value for an incorrect #{value.inspect} (#{value.class}) parameter" do
63+
is_expected.to run.with_params(value, 'default_value')
64+
.and_return('default_value')
65+
end
66+
end
67+
end
68+
end

0 commit comments

Comments
 (0)