@@ -287,6 +287,9 @@ module json_value_module
287287 ! ! * If true [default], an exception will be raised if an integer
288288 ! ! value cannot be read when parsing JSON.
289289
290+ logical (LK) :: allow_trailing_comma = .true.
291+ ! ! Allow a single trailing comma in arrays and objects.
292+
290293 integer :: ichunk = 0 ! ! index in `chunk` for [[pop_char]]
291294 ! ! when `use_unformatted_stream=True`
292295 integer :: filesize = 0 ! ! the file size when when `use_unformatted_stream=True`
@@ -1140,6 +1143,10 @@ subroutine json_initialize(me,&
11401143 me% strict_integer_type_checking = strict_integer_type_checking
11411144 end if
11421145
1146+ if (present (allow_trailing_comma)) then
1147+ me% allow_trailing_comma = allow_trailing_comma
1148+ end if
1149+
11431150 ! Set the format for real numbers:
11441151 ! [if not changing it, then it remains the same]
11451152
@@ -10154,7 +10161,7 @@ recursive subroutine parse_value(json, unit, str, value)
1015410161
1015510162 ! start object
1015610163 call json% to_object(value) ! allocate class
10157- call json% parse_object(unit, str, value)
10164+ call json% parse_object(unit, str, value, expecting_next_element = .false. )
1015810165
1015910166 case (start_array)
1016010167
@@ -10879,14 +10886,17 @@ end subroutine to_array
1087910886! >
1088010887! Core parsing routine.
1088110888
10882- recursive subroutine parse_object (json , unit , str , parent )
10889+ recursive subroutine parse_object (json , unit , str , parent , expecting_next_element )
1088310890
1088410891 implicit none
1088510892
1088610893 class(json_core),intent (inout ) :: json
1088710894 integer (IK),intent (in ) :: unit ! ! file unit number (if parsing from a file)
1088810895 character (kind= CK,len=* ),intent (in ) :: str ! ! JSON string (if parsing from a string)
1088910896 type (json_value),pointer :: parent ! ! the parsed object will be added as a child of this
10897+ logical (LK),intent (in ) :: expecting_next_element ! ! if true, this object is preceeded by a comma, so
10898+ ! ! we expect a valid object to exist. used to check
10899+ ! ! for trailing delimiters.
1089010900
1089110901 type (json_value),pointer :: pair ! ! temp variable
1089210902 logical (LK) :: eof ! ! end of file flag
@@ -10907,13 +10917,18 @@ recursive subroutine parse_object(json, unit, str, parent)
1090710917
1090810918 ! pair name
1090910919 call json% pop_char(unit, str= str, eof= eof, skip_ws= .true. , &
10910- skip_comments= json% allow_comments, popped= c)
10920+ skip_comments= json% allow_comments, popped= c)
1091110921 if (eof) then
1091210922 call json% throw_exception(' Error in parse_object:' // &
1091310923 ' Unexpected end of file while parsing start of object.' )
1091410924 return
1091510925 else if (end_object == c) then
1091610926 ! end of an empty object
10927+ if (expecting_next_element .and. .not. json% allow_trailing_comma) then
10928+ ! this is a dangling comma.
10929+ call json% throw_exception(' Error in parse_object: ' // &
10930+ ' Dangling comma when parsing an object.' )
10931+ end if
1091710932 return
1091810933 else if (quotation_mark == c) then
1091910934 call json_value_create(pair)
@@ -10935,7 +10950,7 @@ recursive subroutine parse_object(json, unit, str, parent)
1093510950
1093610951 ! pair value
1093710952 call json% pop_char(unit, str= str, eof= eof, skip_ws= .true. , &
10938- skip_comments= json% allow_comments, popped= c)
10953+ skip_comments= json% allow_comments, popped= c)
1093910954 if (eof) then
1094010955 call json% destroy(pair)
1094110956 call json% throw_exception(' Error in parse_object:' // &
@@ -10959,14 +10974,15 @@ recursive subroutine parse_object(json, unit, str, parent)
1095910974
1096010975 ! another possible pair
1096110976 call json% pop_char(unit, str= str, eof= eof, skip_ws= .true. , &
10962- skip_comments= json% allow_comments, popped= c)
10977+ skip_comments= json% allow_comments, popped= c)
1096310978 if (eof) then
1096410979 call json% throw_exception(' Error in parse_object: ' // &
1096510980 ' End of file encountered when parsing an object' )
1096610981 return
1096710982 else if (delimiter == c) then
1096810983 ! read the next member
10969- call json% parse_object(unit = unit, str= str, parent = parent)
10984+ call json% parse_object(unit = unit, str= str, parent = parent, &
10985+ expecting_next_element= .true. )
1097010986 else if (end_object == c) then
1097110987 ! end of object
1097210988 return
@@ -10996,6 +11012,9 @@ recursive subroutine parse_array(json, unit, str, array)
1099611012 type (json_value),pointer :: element ! ! temp variable for array element
1099711013 logical (LK) :: eof ! ! end of file flag
1099811014 character (kind= CK,len= 1 ) :: c ! ! character returned by [[pop_char]]
11015+ logical (LK) :: expecting_next_element ! ! to check for trailing delimiters
11016+
11017+ expecting_next_element = .false.
1099911018
1100011019 do
1100111020
@@ -11011,7 +11030,10 @@ recursive subroutine parse_array(json, unit, str, array)
1101111030 end if
1101211031
1101311032 ! parse value will deallocate an empty array value
11014- if (associated (element)) call json% add(array, element)
11033+ if (associated (element)) then
11034+ expecting_next_element = .false.
11035+ call json% add(array, element)
11036+ end if
1101511037
1101611038 ! popped the next character
1101711039 call json% pop_char(unit, str= str, eof= eof, skip_ws= .true. , &
@@ -11024,9 +11046,15 @@ recursive subroutine parse_array(json, unit, str, array)
1102411046 exit
1102511047 else if (delimiter == c) then
1102611048 ! parse the next element
11049+ expecting_next_element = .true.
1102711050 cycle
1102811051 else if (end_array == c) then
1102911052 ! end of array
11053+ if (expecting_next_element .and. .not. json% allow_trailing_comma) then
11054+ ! this is a dangling comma.
11055+ call json% throw_exception(' Error in parse_array: ' // &
11056+ ' Dangling comma when parsing an array.' )
11057+ end if
1103011058 exit
1103111059 else
1103211060 call json% throw_exception(' Error in parse_array: ' // &
0 commit comments