From cfcbf0534b25b846f532d8a235cc1cfbefb06d43 Mon Sep 17 00:00:00 2001 From: Jacob Williams Date: Sun, 30 Sep 2018 21:15:02 -0500 Subject: [PATCH 1/2] Fixed an issue where invalid characters after the main object was parsed in a file were being ignored. Now if this occurs, it raises an exception. Fixes #369 Added unit tests for this case. --- src/json_value_module.F90 | 46 +++++++++++++++++++++++++++++++++++---- src/tests/jf_test_06.F90 | 22 ++++++++++++++----- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/src/json_value_module.F90 b/src/json_value_module.F90 index 900fc626af..f30f1f1832 100644 --- a/src/json_value_module.F90 +++ b/src/json_value_module.F90 @@ -726,6 +726,7 @@ module json_value_module procedure :: json_value_print procedure :: string_to_int procedure :: string_to_dble + procedure :: parse_end => json_parse_end procedure :: parse_value procedure :: parse_number procedure :: parse_string @@ -8708,7 +8709,7 @@ subroutine json_parse_file(json, file, p, unit) logical(LK) :: has_duplicate !! if checking for duplicate keys character(kind=CK,len=:),allocatable :: path !! path to any duplicate key - !clear any exceptions and initialize: + ! clear any exceptions and initialize: call json%initialize() if ( present(unit) ) then @@ -8720,7 +8721,7 @@ subroutine json_parse_file(json, file, p, unit) iunit = unit - !check to see if the file is already open + ! check to see if the file is already open ! if it is, then use it, otherwise open the file with the name given. inquire(unit=iunit, opened=is_open, iostat=istat) if (istat==0 .and. .not. is_open) then @@ -8734,7 +8735,7 @@ subroutine json_parse_file(json, file, p, unit) iostat = istat & FILE_ENCODING ) else - !if the file is already open, then we need to make sure + ! if the file is already open, then we need to make sure ! that it is open with the correct form/access/etc... end if @@ -8763,6 +8764,7 @@ subroutine json_parse_file(json, file, p, unit) ! parse as a value call json%parse_value(unit=iunit, str=CK_'', value=p) + call json%parse_end(unit=iunit, str=CK_'') ! check for errors: if (json%exception_thrown) then @@ -8812,7 +8814,7 @@ subroutine json_parse_string(json, p, str) logical(LK) :: has_duplicate !! if checking for duplicate keys character(kind=CK,len=:),allocatable :: path !! path to any duplicate key - !clear any exceptions and initialize: + ! clear any exceptions and initialize: call json%initialize() ! create the value and associate the pointer @@ -8824,6 +8826,7 @@ subroutine json_parse_string(json, p, str) ! parse as a value call json%parse_value(unit=iunit, str=str, value=p) + call json%parse_end(unit=iunit, str=str) if (json%exception_thrown) then call json%annotate_invalid_json(iunit,str) @@ -8842,6 +8845,41 @@ subroutine json_parse_string(json, p, str) end subroutine json_parse_string !***************************************************************************************** +!***************************************************************************************** +!> +! An error checking routine to call after a file (or string) has been parsed. +! It will throw an exception if there are any other non-whitespace characters +! in the file. + + subroutine json_parse_end(json, unit, str) + + implicit none + + class(json_core),intent(inout) :: json + integer(IK),intent(in) :: unit !! file unit number + character(kind=CK,len=*),intent(in) :: str !! string containing JSON + !! data (only used if `unit=0`) + + logical(LK) :: eof !! end-of-file flag + character(kind=CK,len=1) :: c !! character read from file + !! (or string) by [[pop_char]] + + ! first check for exceptions: + if (json%exception_thrown) return + + ! pop the next non whitespace character off the file + call json%pop_char(unit, str=str, eof=eof, skip_ws=.true., & + skip_comments=json%allow_comments, popped=c) + + if (.not. eof) then + call json%throw_exception('Error in json_parse_end:'//& + ' Unexpected character found after parsing value. "'//& + c//'"') + end if + + end subroutine json_parse_end +!***************************************************************************************** + !***************************************************************************************** !> ! Alternate version of [[json_parse_string]], where `str` is kind=CDK. diff --git a/src/tests/jf_test_06.F90 b/src/tests/jf_test_06.F90 index 23fbab97cb..c8fe6b7a1d 100644 --- a/src/tests/jf_test_06.F90 +++ b/src/tests/jf_test_06.F90 @@ -3,7 +3,7 @@ ! Module for the sixth unit test. ! !# HISTORY -! * Izaak Beekman : 2/18/2015 : Created (refactoried original json_example.f90 file) +! * Izaak Beekman : 2/18/2015 : Created (refactored original json_example.f90 file) module jf_test_6_mod @@ -34,9 +34,13 @@ subroutine test_6(error_cnt) character(kind=CK,len=:),allocatable :: expected_error_msg logical(LK) :: status_ok - character(len=*),dimension(3),parameter :: files = ['invalid.json ',& + character(len=*),dimension(5),parameter :: files = ['invalid.json ',& 'invalid2.json',& - 'invalid3.json'] + 'invalid3.json',& + 'invalid4.json',& + ' '] + + character(len=*),parameter :: invalid_str = '{"a":1} "b": 2}' !! invalid JSON string error_cnt = 0 call json%initialize() @@ -55,9 +59,15 @@ subroutine test_6(error_cnt) ! parse the json file: write(error_unit,'(A)') '' - write(error_unit,'(A)') 'load file: '//trim(files(i)) - write(error_unit,'(A)') '' - call json%load_file(filename = dir//trim(files(i))) + if (files(i)=='') then + write(error_unit,'(A)') 'load string: '//invalid_str + write(error_unit,'(A)') '' + call json%load_from_string(str = invalid_str) + else + write(error_unit,'(A)') 'load file: '//trim(files(i)) + write(error_unit,'(A)') '' + call json%load_file(filename = dir//trim(files(i))) + end if if (json%failed()) then if (i==1) then From 28babb88efb9a6b502a214aa81f55b270ab62c71 Mon Sep 17 00:00:00 2001 From: Jacob Williams Date: Sun, 30 Sep 2018 22:08:46 -0500 Subject: [PATCH 2/2] missing file from last commit. --- files/inputs/invalid4.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 files/inputs/invalid4.json diff --git a/files/inputs/invalid4.json b/files/inputs/invalid4.json new file mode 100644 index 0000000000..6ed72f70d5 --- /dev/null +++ b/files/inputs/invalid4.json @@ -0,0 +1,11 @@ +{ + "a": "blah", + "b": 2 +} + + + + + + +,