Checks a JSON object for duplicate child names.
It uses the specified settings for name matching (see name_strings_equal).
This will only check for one duplicate, it will return the first one that it finds.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(json_core), | intent(inout) | :: | json | |||
type(json_value), | intent(in), | pointer | :: | p | the object to search. If |
|
logical(kind=LK), | intent(out) | :: | has_duplicate | true if there is at least
two children have duplicate
|
||
character(kind=CK,len=:), | intent(out), | optional | allocatable | :: | name | the duplicate name (unallocated if no duplicate was found) |
character(kind=CK,len=:), | intent(out), | optional | allocatable | :: | path | the full path to the duplicate name (unallocated if no duplicate was found) |
subroutine json_check_children_for_duplicate_keys(json,p,has_duplicate,name,path)
implicit none
class(json_core),intent(inout) :: json
type(json_value),pointer,intent(in) :: p !! the object to search. If `p` is
!! not a `json_object`, then `has_duplicate`
!! will be false.
logical(LK),intent(out) :: has_duplicate !! true if there is at least
!! two children have duplicate
!! `name` values.
character(kind=CK,len=:),allocatable,intent(out),optional :: name !! the duplicate name
!! (unallocated if no
!! duplicate was found)
character(kind=CK,len=:),allocatable,intent(out),optional :: path !! the full path to the
!! duplicate name
!! (unallocated if no
!! duplicate was found)
integer(IK) :: i !! counter
integer(IK) :: j !! counter
type(json_value),pointer :: child !! pointer to a child of `p`
integer(IK) :: n_children !! number of children of `p`
logical(LK) :: found !! flag for `get_child`
type :: alloc_str
!! so we can have an array of allocatable strings
character(kind=CK,len=:),allocatable :: str !! name string
end type alloc_str
type(alloc_str),dimension(:),allocatable :: names !! array of all the
!! child name strings
! initialize:
has_duplicate =.false.
if (.not. json%exception_thrown) then
if (associated(p)) then
if (p%var_type==json_object) then
! number of items to check:
n_children = json%count(p)
allocate(names(n_children))
! first get a list of all the name keys:
do i=1, n_children
call json%get_child(p,i,child,found) ! get by index
if (.not. found) then
call json%throw_exception(&
'Error in json_check_children_for_duplicate_keys: '//&
'Malformed JSON linked list')
exit
end if
if (allocated(child%name)) then
names(i)%str = child%name
else
call json%throw_exception(&
'Error in json_check_children_for_duplicate_keys: '//&
'Object child name is not allocated')
exit
end if
end do
if (.not. json%exception_thrown) then
! now check the list for duplicates:
main: do i=1,n_children
do j=1,i-1
if (json%name_strings_equal(names(i)%str,names(j)%str)) then
has_duplicate = .true.
if (present(name)) then
name = names(i)%str
end if
if (present(path)) then
call json%get_child(p,names(i)%str,child,found) ! get by name
if (found) then
call json%get_path(child,path,found)
if (.not. found) then
! should never happen since we know it is there
call json%throw_exception(&
'Error in json_check_children_for_duplicate_keys: '//&
'Could not get path')
end if
else
! should never happen since we know it is there
call json%throw_exception(&
'Error in json_check_children_for_duplicate_keys: '//&
'Could not get child: '//trim(names(i)%str))
end if
end if
exit main
end if
end do
end do main
end if
! cleanup
do i=1,n_children
if (allocated(names(i)%str)) deallocate(names(i)%str)
end do
if (allocated(names)) deallocate(names)
end if
end if
end if
end subroutine json_check_children_for_duplicate_keys