Print the JSON structure to a string or a file.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(json_core), | intent(inout) | :: | json | |||
type(json_value), | intent(in), | pointer | :: | p | ||
integer(kind=IK), | intent(in) | :: | iunit | file unit to write to (6=console) |
||
character(kind=CK,len=:), | intent(inout), | allocatable | :: | str | if iunit==unit2str (-1) then the structure is printed to this string rather than a file. This mode is used by json_value_to_string. |
|
integer(kind=IK), | intent(in), | optional | :: | indent | indention level |
|
logical(kind=LK), | intent(in), | optional | :: | need_comma | if it needs a comma after it |
|
logical(kind=LK), | intent(in), | optional | :: | colon | if the colon was just written |
|
logical(kind=LK), | intent(in), | optional | :: | is_array_element | if this is an array element |
recursive subroutine json_value_print(json,p,iunit,str,indent,&
need_comma,colon,is_array_element)
implicit none
class(json_core),intent(inout) :: json
type(json_value),pointer,intent(in) :: p
integer(IK),intent(in) :: iunit !! file unit to write to (6=console)
integer(IK),intent(in),optional :: indent !! indention level
logical(LK),intent(in),optional :: is_array_element !! if this is an array element
logical(LK),intent(in),optional :: need_comma !! if it needs a comma after it
logical(LK),intent(in),optional :: colon !! if the colon was just written
character(kind=CK,len=:),intent(inout),allocatable :: str
!! if iunit==unit2str (-1) then the structure is
!! printed to this string rather than
!! a file. This mode is used by
!! [[json_value_to_string]].
character(kind=CK,len=max_numeric_str_len) :: tmp !for val to string conversions
character(kind=CK,len=:),allocatable :: s
type(json_value),pointer :: element
integer(IK) :: tab, i, count, spaces
logical(LK) :: print_comma
logical(LK) :: write_file, write_string
logical(LK) :: is_array
if (.not. json%exception_thrown) then
!whether to write a string or a file (one or the other):
write_string = (iunit==unit2str)
write_file = .not. write_string
!if the comma will be printed after the value
! [comma not printed for the last elements]
if (present(need_comma)) then
print_comma = need_comma
else
print_comma = .false.
end if
!number of "tabs" to indent:
if (present(indent) .and. .not. json%no_whitespace) then
tab = indent
else
tab = 0
end if
!convert to number of spaces:
spaces = tab*json%spaces_per_tab
!if this is an element in an array:
if (present(is_array_element)) then
is_array = is_array_element
else
is_array = .false.
end if
!if the colon was the last thing written
if (present(colon)) then
s = ''
else
s = repeat(space, spaces)
end if
select case (p%var_type)
case (json_object)
count = json%count(p)
if (count==0) then !special case for empty object
call write_it( s//start_object//end_object, comma=print_comma )
else
call write_it( s//start_object )
!if an object is in an array, there is an extra tab:
if (is_array) then
if ( .not. json%no_whitespace) tab = tab+1
spaces = tab*json%spaces_per_tab
end if
nullify(element)
element => p%children
do i = 1, count
if (.not. associated(element)) then
call json%throw_exception('Error in json_value_print: '//&
'Malformed JSON linked list')
return
end if
! print the name
if (allocated(element%name)) then
if (json%no_whitespace) then
!compact printing - no extra space
call write_it(repeat(space, spaces)//quotation_mark//&
element%name//quotation_mark//colon_char,&
advance=.false.)
else
call write_it(repeat(space, spaces)//quotation_mark//&
element%name//quotation_mark//colon_char//space,&
advance=.false.)
end if
else
call json%throw_exception('Error in json_value_print:'//&
' element%name not allocated')
nullify(element)
return
end if
! recursive print of the element
call json%json_value_print(element, iunit=iunit, indent=tab + 1, &
need_comma=i<count, colon=.true., str=str)
! get the next child the list:
element => element%next
end do
! [one fewer tab if it isn't an array element]
if (.not. is_array) s = repeat(space, max(0,spaces-json%spaces_per_tab))
call write_it( s//end_object, comma=print_comma )
nullify(element)
end if
case (json_array)
count = json%count(p)
if (count==0) then !special case for empty array
call write_it( s//start_array//end_array, comma=print_comma )
else
call write_it( start_array )
nullify(element)
element => p%children
do i = 1, count
if (.not. associated(element)) then
call json%throw_exception('Error in json_value_print: '//&
'Malformed JSON linked list')
return
end if
! recursive print of the element
call json%json_value_print(element, iunit=iunit, indent=tab,&
need_comma=i<count, is_array_element=.true., str=str)
! get the next child the list:
element => element%next
end do
!indent the closing array character:
call write_it( repeat(space, max(0,spaces-json%spaces_per_tab))//end_array,&
comma=print_comma )
nullify(element)
end if
case (json_null)
call write_it( s//null_str, comma=print_comma )
case (json_string)
if (allocated(p%str_value)) then
call write_it( s//quotation_mark// &
trim(p%str_value)//quotation_mark, comma=print_comma )
else
call json%throw_exception('Error in json_value_print:'//&
' p%value_string not allocated')
return
end if
case (json_logical)
if (p%log_value) then
call write_it( s//true_str, comma=print_comma )
else
call write_it( s//false_str, comma=print_comma )
end if
case (json_integer)
call integer_to_string(p%int_value,int_fmt,tmp)
call write_it( s//trim(tmp), comma=print_comma )
case (json_double)
if (allocated(json%real_fmt)) then
call real_to_string(p%dbl_value,json%real_fmt,json%compact_real,tmp)
else
!use the default format (user has not called initialize() or specified one):
call real_to_string(p%dbl_value,default_real_fmt,json%compact_real,tmp)
end if
call write_it( s//trim(tmp), comma=print_comma )
case default
call json%throw_exception('Error in json_value_print: unknown data type')
end select
!cleanup:
if (allocated(s)) deallocate(s)
end if
contains
subroutine write_it(s,advance,comma)
!! write the string to the file (or the output string)
implicit none
character(kind=CK,len=*),intent(in) :: s !! string to print
logical(LK),intent(in),optional :: advance !! to add line break or not
logical(LK),intent(in),optional :: comma !! print comma after the string
logical(LK) :: add_comma !! if a delimiter is to be added after string
logical(LK) :: add_line_break !! if a line break is to be added after string
character(kind=CK,len=:),allocatable :: s2 !! temporary string
if (present(comma)) then
add_comma = comma
else
add_comma = .false. !default is not to add comma
end if
if (present(advance)) then
add_line_break = advance
else
add_line_break = .not. json%no_whitespace ! default is to advance if
! we are printing whitespace
end if
!string to print:
s2 = s
if (add_comma) s2 = s2 // delimiter
if (write_file) then
if (add_line_break) then
write(iunit,fmt='(A)') s2
else
write(iunit,fmt='(A)',advance='NO') s2
end if
else !write string
str = str // s2
if (add_line_break) str = str // newline
end if
!cleanup:
if (allocated(s2)) deallocate(s2)
end subroutine write_it
end subroutine json_value_print