Skip to content

Commit 99a9254

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 99a9254

File tree

3 files changed

+144
-0
lines changed

3 files changed

+144
-0
lines changed

REFERENCE.md

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

39443993
> *Note:*

lib/puppet/functions/parsepson.rb

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

spec/functions/parsepson_spec.rb

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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{'parsepson' expects between 1 and 2 arguments, got none}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('invalid')
53+
.and_raise_error(PSON::ParserError)
54+
end
55+
56+
it "returns the default value for an invalid PSON and a given default" do
57+
is_expected.to run.with_params('invalid', 'default_value')
58+
.and_return('default_value')
59+
end
60+
61+
it 'supports a structure for a default value' do
62+
is_expected.to run.with_params('invalid', 'a' => '1')
63+
.and_return('a' => '1')
64+
end
65+
end
66+
end

0 commit comments

Comments
 (0)