OUR SITES NetworkRADIUS FreeRADIUS

JSON Module

The json module registers a map function to allow mapping fields from JSON structures to attributes. It also adds some xlats for processing and generating JSON documents.

JSON 'map' function

The path through the JSON document’s tree is specified with FR jpath, which is the FreeRADIUS implementation of the jpath grammar described at http://goessner.net/articles/JsonPath/

Selectors currently implemented are:

Selector Description

$

Root node (only valid at the start of the path).

@

Current node (only valid at the start of the path).

.<name>

A field within an object.

[<idx>]

Index within an array.

[<start>:<end>[:<step>]]

A slice within an array (identical to the Python syntax).

[<idx>,<start>:<end>]

Multiple indexes/slices within an array.

.*

All the children of the current node.

..

Recursive descent.

  • Automatic casting will occur between JSON and attribute types where possible.

  • Assignment of JSON objects/arrays to strings is supported, in which case the JSON serialized form of the object/array is used.

  • If a jpath matches multiple nodes, unless the map includes the += operator

  • only the first node’s value will be used.

  • If the map uses += then multiple instances of the attribute will be created, each holding a different node value.

Sample

Assuming that the URL http://example.org/api/user/$username replies with some JSON content as below.

{
  "user": "bob",
  "account number": 7124503,
  "groups": [
    "admin",
    "networks",
    "bob"
  ]
}

In this case, the rest module can be used to get the JSON data and the fields can be accessed using 'map' as shown in the example below.

map json "%rest(GET http://example.org/api/user/%{User-Name})" {
  &Foo            := '$.account number'
  &Group          += '$.groups.*'
}

Configuration Settings

The only options for the JSON module are to control the output format of the json.encode xlat.

output_mode

set the format of JSON documenta that should be created. This may be one of:

  • object

  • object_simple

  • array

  • array_of_names

  • array_of_values

Examples of each format are given below.

Formatting options for attribute names

prefix

Add a colon-delimited prefix to all attribute names in the output document. For example, with a prefix of "foo", User-Name will be output as foo:User-Name.

Formatting options for attribute values

single_value_as_array

always put values in an array

Output formats will by default put single values as a JSON object (string, integer, etc). More than one value will, depending on the output format, be added as an array.

When this option is enabled, values will always be added as an array.

enum_as_integer

output the integer value of enumerated attributes

Where an attribute has enum values, the textual representation of the value will normally be output. Enable this option to force the numeric value instead.

always_string

force all values to be strings

Integer values are normally written to the JSON document as numbers (i.e. without quotes). Enable this option to force all values to be as quoted strings.

Expansions

rlm_json provides the below xlat functions to handle the JSON documents.

%json.jpath_validate(…​)

Determine if a jpath expression is valid.

Validate parser for everything except unions and expressions.
Example
string payload
payload := '$.my.json.payload[1]'
&reply.Reply-Message := "Validation of %{payload} is %json.jpath_validate($.my.json.payload[1])"
Output
Validation of $.my.json.payload[1] is 20:$.my.json.payload[1]

%json.quote(…​)

Escapes string for use as a JSON string.

Example
string path
&path := "caipirinha/gelada"
&reply.Reply-Message := "The string %{path} should be %json.quote(%{path}) to be a valid JSON string."
Output
The string caipirinha/gelada should be caipirinha\\/gelada to be a valid JSON string.

%json.encode(…​)

Generates a JSON document from a given list of attribute templates. The format of document generated can be controlled with the 'encode' section in the module configuration. Attribute values will automatically be escaped so they are JSON-safe.

The name of the xlat is based on the instance name of this module. If the module was defined as json jdoc {…​}, then the xlat name will be jdoc_encode.

The xlat should be passed a list of attributes to encode. Each attribute (after template expansion) will be added to a list of attributes to include in the JSON document. If any of the attributes given are preceded with a ! then they are removed from the list. Once all attributes have been processed, the JSON document will be created using this list.

For example, the following will produce a JSON document with two attributes in it, User-Name and Calling-Station-Id, from the RADIUS request:

Example
%json.encode(&User-Name, &Calling-Station-Id)

The following will include all attributes in the RADIUS request, except for User-Password:

Example
%json.encode(&request[*], !&User-Password)

In another (contrived) example, all the attributes in the RADIUS request will be included in the document, except any attributes in the RADIUS reply. &User-Name will be included from the control list, too, if it exists:

Example
%json.encode(&request[*], !&reply[*], &control.User-Name)

Output format modes

There are a number of output modes, each generating a different format of JSON document.

In the JSON document, "type" is the type of the attribute, which is not necessarily the same as the type of the "value" in the document. See e.g. Login-Service above, an enumerated value.

The following examples assume the three attributes are being added to the JSON document:

User-Name = bob
Filter-Id = ab
Filter-Id += cd

Object output mode examples

These modes output a JSON object.

Output mode "object"
{
  "User-Name": {
    "type": "string",
    "value": "bob"
  },
  "Filter-Id": {
    "type": "string",
    "value": ["ab","cd"]
  }
}
Output mode "object_simple"
{
  "User-Name": "bob",
  "Filter-Id": ["ab","cd"]
}

Array output mode examples

The "array" mode is a list of objects, each containing an attribute. If the "single_value_as_array" value option is set then each attribute will only appear once in the array, and "value" will be a list of all the values from the same attribute.

Output mode "array"
[
  {
    "name": "User-Name",
    "type": "string",
    "value": "bob"
  },
  {
    "name": "Filter-Id",
    "type": "string",
    "value": "ab"
  },
  {
    "name": "Filter-Id",
    "type": "string",
    "value": "cd"
  }
]
Output mode "array" when "single_value_as_array" is also set
[
  {
    "name": "User-Name",
    "type": "string",
    "value": ["bob"]
  },
  {
    "name": "Filter-Id",
    "type": "string",
    "value": ["ab","cd"]
  }
]

The following output modes either do not include the attribute names or values. They are likely to be useful only when the attributes are individually specified and guaranteed to exist. In this case the attribute names in array_of_names will have corresponding indexes to the values in array_of_values.

Output mode "array_of_names"
[
  "User-Name",
  "Filter-Id",
  "Filter-Id"
]
Output mode "array_of_values"
[
  "bob",
  "ab",
  "cd"
]

Default Configuration

json {
	encode {
#		output_mode = object
		attribute {
#			prefix =
		}
		value {
#			single_value_as_array = no
#			enum_as_integer = no
#			always_string = no
		}
	}
}