texlive[72742] Master/texmf-dist: jsonparse (1nov24)

commits+karl at tug.org commits+karl at tug.org
Fri Nov 1 22:26:45 CET 2024


Revision: 72742
          https://tug.org/svn/texlive?view=revision&revision=72742
Author:   karl
Date:     2024-11-01 22:26:45 +0100 (Fri, 01 Nov 2024)
Log Message:
-----------
jsonparse (1nov24)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/jsonparse/README.md
    trunk/Master/texmf-dist/doc/latex/jsonparse/jsonparse-doc.pdf
    trunk/Master/texmf-dist/doc/latex/jsonparse/jsonparse-doc.tex
    trunk/Master/texmf-dist/tex/latex/jsonparse/jsonparse.sty

Modified: trunk/Master/texmf-dist/doc/latex/jsonparse/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/jsonparse/README.md	2024-11-01 21:26:35 UTC (rev 72741)
+++ trunk/Master/texmf-dist/doc/latex/jsonparse/README.md	2024-11-01 21:26:45 UTC (rev 72742)
@@ -1,4 +1,4 @@
-![Version 0.9.5](https://img.shields.io/badge/version-0.9.5-blue)
+![Version 0.9.6](https://img.shields.io/badge/version-0.9.6-blue)
 
 ![Jason, the JSON parsing horse](https://github.com/jasperhabicht/jsonparse/assets/6378801/ddfddc70-bf5f-4121-ba45-4b9128875d85)
 

Modified: trunk/Master/texmf-dist/doc/latex/jsonparse/jsonparse-doc.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/jsonparse/jsonparse-doc.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/jsonparse/jsonparse-doc.tex	2024-11-01 21:26:35 UTC (rev 72741)
+++ trunk/Master/texmf-dist/doc/latex/jsonparse/jsonparse-doc.tex	2024-11-01 21:26:45 UTC (rev 72742)
@@ -11,8 +11,8 @@
 % This work has the LPPL maintenance status `maintained'.
 % 
 \documentclass[a4paper]{article}
-\def\jsonparsefileversion{0.9.5}
-\def\jsonparsefiledate{27 October 2024}
+\def\jsonparsefileversion{0.9.6}
+\def\jsonparsefiledate{31 October 2024}
 
 \usepackage[T1]{fontenc}
 \usepackage{Alegreya}
@@ -204,6 +204,7 @@
 \changes{v0.9.1}{2024/09/21}{Added functions to test for valid JSON numbers.}
 \changes{v0.9.3}{2024/10/24}{Fixed a bug that prevented tabs in source from being parsed properly.}
 \changes{v0.9.5}{2024/10/27}{Streamlining of code, clarification of explanations in documentation.}
+\changes{v0.9.6}{2024/10/31}{Allowing for multiple return values when mapping over arrays.}
 
 \begin{document}
 \vspace*{-1cm}
@@ -354,21 +355,20 @@
   ]
 }
 \end{codeexample}
+\JSONParse{\myJSONdata}{ { "array" : [ { "key_a" : "one" , "key_b" : "two" } , { "key_a" : "three" , "key_b" : "four" } ] } }
 
-Then, when using \macro{\JSONParseArrayValues{\myJSONdata}{array}[key_a]{, }}, `one, three' is typeset to the document. 
+Then, when using \macro{\JSONParseArrayValues{\myJSONdata}{array}[key_a]{, }}, `\JSONParseArrayValues{\myJSONdata}{array}[key_a]{, }' is typeset to the document. 
 
 The first optional argument can be used to pass options to the command, such as \macro{escape} or \macro{rescan}, that are then applied locally. 
 
 \begin{macrodef}
 |\JSONParseArrayValuesMap|[<options>]{<token variable>}{<key>}[<subkey>]
-    {<command name>}
+    {<command name>}[<before code>][<after code>]
 \end{macrodef}
-The command \macro{\JSONParseArrayValuesMap} takes the same first three arguments as the command \macro{\JSONParseArrayValues} and works in a similar way. However, instead of a string that is added between the array items, it takes a command name as fourth argument. This command can be defined beforehand and will be called for every array item. Inside its definition, the commands \macro{\JSONParseArrayIndex}, \macro{\JSONParseArrayKey} and \macro{\JSONParseArrayValue} can be used which are updated for each item and output the index, the key and the value of the current item respectively. 
+The command \macro{\JSONParseArrayValuesMap} takes the same first three arguments as the command \macro{\JSONParseArrayValues} and works in a similar way. However, instead of a string that is added between the array items, it takes a command name as fourth argument. This command can be defined beforehand and will be called for every array item. Inside its definition, the commands \macro{\JSONParseArrayIndex}, \macro{\JSONParseArrayKey} and \macro{\JSONParseArrayValue} can be used which are updated for each item and output the index, the key and the value of the current item respectively. Note that these commands are defined globally to make accessing them as easy as possible.
 
 For example, let us assume the same JSON data structure as defined above parsed into the token variable \macro{\myJSONdata}. Then, the following can be done:
 
-\JSONParse{\myJSONdata}{ { "array" : [ { "key_a" : "one" , "key_b" : "two" } , { "key_a" : "three" , "key_b" : "four" } ] } }
-
 \begin{codeexamplecolumns}
 \newcommand{\myJSONitem}{
   \item \emph{\JSONParseArrayValue}
@@ -380,8 +380,44 @@
 \end{itemize}
 \end{codeexamplecolumns}
 
-The first optional argument can be used to pass options to the command, such as \macro{escape} or \macro{rescan}, that are then applied locally. 
+It is possible to make use of multiple subkeys by passing them as a comma separated list as third argument to the command. Inside the command that is called for every array item, the different keys and values can be access via commands numbered with uppercase Roman numerals such as \macro{\JSONParseArrayKeyI}, \macro{\JSONParseArrayKeyII}, \macro{\JSONParseArrayKeyIII} etc.\ and \macro{\JSONParseArrayValueI}, \macro{\JSONParseArrayValueII}, \macro{\JSONParseArrayValueIII} etc.
 
+We can extend the above example in the following way:
+
+\begin{codeexamplecolumns}
+\newcommand{\myJSONitem}{
+  \item \emph{\JSONParseArrayValueI :} 
+    \JSONParseArrayValueII
+}
+
+\begin{itemize}
+  \JSONParseArrayValuesMap{\myJSONdata}
+    {array}[key_a,key_b]{myJSONitem}
+\end{itemize}
+\end{codeexamplecolumns}
+
+The command additionally takes two optional arguments at sixth and seventh position. These arguments can be used to place code before and after the output that is generated by the command called for every array item, for example for typesetting tabular contents. To this end, the command \macro{\JSONParseArrayNewline} can be used to make sure that tabular newlines are typeset properly.
+
+Typesetting the above example in a tabular way can be achieved as follows:
+
+\begin{codeexamplecolumns}
+\newcommand{\myJSONitem}{
+  \JSONParseArrayValueI &
+  \JSONParseArrayValueII
+    \JSONParseArrayNewline
+}
+
+\JSONParseArrayValuesMap{\myJSONdata}
+  {array}[key_a,key_b]{myJSONitem}
+  [\begin{tabular}{ c c }
+    \textbf{key a} & 
+    \textbf{key b} \\ \hline]
+  [\\ \hline 
+    \end{tabular}]
+\end{codeexamplecolumns}
+
+Finally, the first optional argument of the command can be used to pass options to the command, such as \macro{escape} or \macro{rescan}, that are then applied locally. 
+
 \begin{macrodef}
 |\JSONParseArrayCount|{<token variable>}{<key>}
 \end{macrodef}
@@ -498,6 +534,11 @@
 The command \macro{\jsonparse_parse_to_prop:Nn} processes the token variable given as the first arguments as property list and filters it according to the key given as second argument. Filtering means that for every entry in the property list, the key of this entry is compared against the key given to the command. If the key in the property list starts with the given key, the matching part is removed from the key in the property list. If the keys do not match, the entry is completely removed from the property list. 
 
 \begin{macrodef}
+|\jsonparse_array_count:NN| <token variable> <integer variable>
+\end{macrodef}
+The command \macro{\jsonparse_array_count:NN} processes the token variable given as the first arguments as property list and, assuming that it is an array, counts its items and stores the result in the integer variable. If the token variable does not expand to a key that represents an array item, that is if the key does not start with the character defined by \macro{separator/array left}, the command will return an error. The command \macro{\JSONParseArrayCount} serves as a wrapper of this command.
+
+\begin{macrodef}
 |\jsonparse_if_num:nTF| {<string>} {<true code>} {<false code>}
 |\jsonparse_if_num:nT| {<string>} {<true code>} 
 |\jsonparse_if_num:nF| {<string>} {<false code>}

Modified: trunk/Master/texmf-dist/tex/latex/jsonparse/jsonparse.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/jsonparse/jsonparse.sty	2024-11-01 21:26:35 UTC (rev 72741)
+++ trunk/Master/texmf-dist/tex/latex/jsonparse/jsonparse.sty	2024-11-01 21:26:45 UTC (rev 72742)
@@ -1,23 +1,23 @@
-% File: jsonparse.sty 
+% File: jsonparse.sty
 % Copyright 2024 Jasper Habicht (mail(at)jasperhabicht.de).
-% 
+%
 % This work may be distributed and/or modified under the
 % conditions of the LaTeX Project Public License version 1.3c,
 % available at http://www.latex-project.org/lppl/.
-% 
+%
 % This file is part of the `jsonparse' package (The Work in LPPL)
 % and all files in that bundle must be distributed together.
-% 
+%
 % This work has the LPPL maintenance status `maintained'.
-% 
-\ProvidesExplPackage {jsonparse} {2024-10-27} {0.9.5} 
+%
+\ProvidesExplPackage {jsonparse} {2024-10-31} {0.9.6}
   {A handy way to parse, store and access JSON data from files or strings in LaTeX documents}
 
 \bool_new:N \l__jsonparse_debug_mode_bool
-\keys_define:nn { jsonparse / global } { 
+\keys_define:nn { jsonparse / global } {
   debug .bool_set:N = \l__jsonparse_debug_mode_bool ,
   debug .default:n  = { true } ,
-  debug .initial:n  = { false } 
+  debug .initial:n  = { false }
 }
 \ProcessKeyOptions [ jsonparse / global ]
 
@@ -28,13 +28,13 @@
 \msg_new:nnn { jsonparse } { parsing-error } {
   \msg_error_text:n { jsonparse } \iow_newline:
   Could ~ not ~ parse ~ JSON. \iow_newline:
-  Parsing ~ error ~ at ~ key ~ `#1` ~ with ~ value ~ `#2`. 
+  Parsing ~ error ~ at ~ key ~ `#1` ~ with ~ value ~ `#2`.
 }
 
 \msg_new:nnn { jsonparse } { nested-non-expandable } {
   \msg_error_text:n { jsonparse } \iow_newline:
   Nested ~ use ~ of ~ \token_to_str:N \JSONParseValue \c_space_tl not ~ allowed. \iow_newline:
-  Use ~ \token_to_str:N \JSONParseExpandableValue \c_space_tl instead. 
+  Use ~ \token_to_str:N \JSONParseExpandableValue \c_space_tl instead.
 }
 
 \msg_new:nnn { jsonparse } { file-not-found } {
@@ -44,7 +44,7 @@
 
 \msg_new:nnn { jsonparse } { file-exists } {
   \msg_error_text:n { jsonparse } \iow_newline:
-  File ~ #1 ~ already ~ existing. 
+  File ~ #1 ~ already ~ existing.
 }
 
 \msg_new:nnn { jsonparse } { escape-in-key } {
@@ -72,6 +72,11 @@
   Loading ~ from ~ external ~ file: ~ #1.
 }
 
+\msg_new:nnn { jsonparse } { not-array-item } {
+	\msg_info_text:n { jsonparse } \iow_newline:
+	Key ~ does ~ not ~ represent ~ an ~ array ~ item: ~ #1
+}
+
 % ===
 
 \str_new:N \l_jsonparse_externalize_prefix_str
@@ -100,12 +105,12 @@
 
 \clist_const:Nn \c__jsonparse_escape_tex_chars_clist {
   number_sign ,
-  dollar_sign , 
+  dollar_sign ,
   percent_sign ,
   ampersand ,
-  circumflex_accent , 
-  low_line , 
-  tilde 
+  circumflex_accent ,
+  low_line ,
+  tilde
 }
 
 \str_new:N \l__jsonparse_escape_temp_str
@@ -120,7 +125,7 @@
   externalize ~ prefix        .str_set:N  = \l_jsonparse_externalize_prefix_str ,
   externalize ~ prefix        .initial:n  = { } ,
   externalize ~ file ~ name   .tl_set:N   = \l__jsonparse_externalize_file_name_tl ,
-  externalize ~ file ~ name   .initial:n  = { 
+  externalize ~ file ~ name   .initial:n  = {
     \l_jsonparse_externalize_prefix_str \c_sys_jobname_str \c_underscore_str \l_jsonparse_current_prop_str
   } ,
   separator                   .code:n     = { \keys_set:nn { jsonparse / parse / separator } {#1} } ,
@@ -142,7 +147,7 @@
   replace / false             .str_set:N  = \l__jsonparse_false_str ,
   replace / false             .initial:n  = { false } ,
   replace / null              .str_set:N  = \l__jsonparse_null_str ,
-  replace / null              .initial:n  = { null } 
+  replace / null              .initial:n  = { null }
 }
 
 \keys_define:nn { jsonparse / typeset } {
@@ -157,13 +162,13 @@
   replace / carriage ~ return .initial:n  = { ~ } ,
   replace / horizontal ~ tab  .str_set:N  = \l__jsonparse_horizontal_tab_str ,
   replace / horizontal ~ tab  .initial:n  = { ~ } ,
-  escape                      .code:n     = { 
-    \str_case:nnF {#1} { 
+  escape                      .code:n     = {
+    \str_case:nnF {#1} {
       { all } {
         \clist_map_inline:Nn \c__jsonparse_escape_tex_chars_clist {
           \bool_set_true:c { l__jsonparse_escape_ ##1 _bool }
         }
-      } 
+      }
       { none } {
         \clist_map_inline:Nn \c__jsonparse_escape_tex_chars_clist {
           \bool_set_false:c { l__jsonparse_escape_ ##1 _bool }
@@ -176,7 +181,7 @@
         \bool_if_exist:cTF { l__jsonparse_escape_ \l__jsonparse_escape_temp_str _bool } {
           \bool_set_true:c { l__jsonparse_escape_ \l__jsonparse_escape_temp_str _bool }
         } {
-          \str_case:nnF {##1} { 
+          \str_case:nnF {##1} {
             { hash } {
               \bool_set_true:c { l__jsonparse_escape_number_sign_bool }
             }
@@ -211,13 +216,13 @@
   \clist_map_inline:Nn \l__jsonparse_unused_keys_clist {
     \msg_warning:nne { jsonparse } { unknown-key } {
       ##1
-    } 
+    }
   }
 }
 
 \NewDocumentCommand { \JSONParseSet } { m } {
   \keys_set_known:nnN { jsonparse / global } {#1} \l__jsonparse_unused_keys_clist
-  \keys_set_known:noN { jsonparse / parse } { \l__jsonparse_unused_keys_clist } \l__jsonparse_unused_keys_clist 
+  \keys_set_known:noN { jsonparse / parse } { \l__jsonparse_unused_keys_clist } \l__jsonparse_unused_keys_clist
   \keys_set_known:noN { jsonparse / typeset } { \l__jsonparse_unused_keys_clist } \l__jsonparse_unused_keys_clist
   \__jsonparse_warning_unused_keys:
 }
@@ -224,7 +229,7 @@
 
 % ===
 
-\cs_if_exist:NF \str_casefold:n { 
+\cs_if_exist:NF \str_casefold:n {
   \cs_new:Npn \str_casefold:n { \str_foldcase:n }
 }
 
@@ -258,7 +263,7 @@
 \prg_generate_conditional_variant:Nnn \tl_if_eq:nn { en } { T }
 \prg_generate_conditional_variant:Nnn \tl_if_head_eq_charcode:nN { oN } { T , TF }
 \prg_generate_conditional_variant:Nnn \tl_if_in:nn { nV } { F }
-\prg_generate_conditional_variant:Nnn \str_if_eq:nn { en , eV } { T , TF }
+\prg_generate_conditional_variant:Nnn \str_if_eq:nn { en , eV } { T , F , TF }
 
 \prop_new:N \g_jsonparse_entries_prop
 \prop_new:N \l__jsonparse_temp_prop
@@ -277,6 +282,9 @@
 \int_new:N \l__jsonparse_array_count_int
 \int_new:N \l__jsonparse_array_count_last_int
 
+\int_new:N \l__jsonparse_array_keys_index_int
+\tl_new:N \l__jsonparse_array_keys_index_roman_tl
+
 \bool_new:N \l__jsonparse_prop_map_first_bool
 \bool_new:N \l__jsonparse_externalize_load_bool
 
@@ -298,26 +306,26 @@
 \tl_new:N \l__jsonparse_num_input_tl
 \tl_new:N \l__jsonparse_num_remainder_tl
 \tl_new:N \l__jsonparse_num_input_last_tl
-\bool_new:N \l__jsonparse_num_bool 
-\bool_new:N \l__jsonparse_num_zero_seen_bool 
-\bool_new:N \l__jsonparse_num_plus_minus_seen_bool 
-\bool_new:N \l__jsonparse_num_fraction_seen_bool 
+\bool_new:N \l__jsonparse_num_bool
+\bool_new:N \l__jsonparse_num_zero_seen_bool
+\bool_new:N \l__jsonparse_num_plus_minus_seen_bool
+\bool_new:N \l__jsonparse_num_fraction_seen_bool
 \bool_new:N \l__jsonparse_num_exponent_seen_bool
 
 \clist_const:Nn \c__jsonparse_num_digits_clist {
-  0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 
+  0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9
 }
 
 \clist_const:Ne \c__jsonparse_num_others_clist {
-  \tl_to_str:n { + } , 
-  \tl_to_str:n { - } , 
-  \tl_to_str:n { . } , 
-  \tl_to_str:n { e } , 
+  \tl_to_str:n { + } ,
+  \tl_to_str:n { - } ,
+  \tl_to_str:n { . } ,
+  \tl_to_str:n { e } ,
   \tl_to_str:n { E }
 }
 
 \prg_new_conditional:Npnn \jsonparse_if_num:n #1 { p , T , F , TF } {
-  \bool_set_true:N \l__jsonparse_num_bool    
+  \bool_set_true:N \l__jsonparse_num_bool
   \bool_set_false:N \l__jsonparse_num_zero_seen_bool
   \bool_set_false:N \l__jsonparse_num_plus_minus_seen_bool
   \bool_set_false:N \l__jsonparse_num_fraction_seen_bool
@@ -324,12 +332,12 @@
   \bool_set_false:N \l__jsonparse_num_exponent_seen_bool
   \tl_set:Nn \l__jsonparse_num_remainder_tl { #1 }
   \tl_if_empty:NTF \l__jsonparse_num_remainder_tl {
-    \bool_set_false:N \l__jsonparse_num_bool  
+    \bool_set_false:N \l__jsonparse_num_bool
   } {
     \__jsonparse_parse_num:n {#1}
   }
   \clist_if_in:NVT \c__jsonparse_num_others_clist \l__jsonparse_num_input_last_tl {
-    \bool_set_false:N \l__jsonparse_num_bool 
+    \bool_set_false:N \l__jsonparse_num_bool
   }
   \bool_if:NTF \l__jsonparse_num_bool {
     \prg_return_true:
@@ -341,43 +349,43 @@
 \cs_new:Npn \__jsonparse_parse_num:n #1 {
   \tl_set:Ne \l__jsonparse_num_input_tl { \tl_trim_spaces:e {#1} }
   \tl_if_empty:NF \l__jsonparse_num_input_tl {
-    \cs_if_exist_use:cTF { __jsonparse_parse_num_ \str_head_ignore_spaces:o { \l__jsonparse_num_input_tl } :w } { 
+    \cs_if_exist_use:cTF { __jsonparse_parse_num_ \str_head_ignore_spaces:o { \l__jsonparse_num_input_tl } :w } {
       \l__jsonparse_num_input_tl \q_stop
     } {
-      \exp_last_unbraced:No 
-      \__jsonparse_parse_num_other:w \l__jsonparse_num_input_tl \q_stop 
+      \exp_last_unbraced:No
+      \__jsonparse_parse_num_other:w \l__jsonparse_num_input_tl \q_stop
     }
   }
 }
 
 \cs_new:cpn { __jsonparse_parse_num_ + :w } #1 \q_stop {
-  \exp_last_unbraced:No 
+  \exp_last_unbraced:No
     \__jsonparse_parse_num_plus_minus:w #1 \q_stop
 }
 
 \cs_new:cpn { __jsonparse_parse_num_ - :w } #1 \q_stop {
-  \exp_last_unbraced:No 
+  \exp_last_unbraced:No
     \__jsonparse_parse_num_plus_minus:w #1 \q_stop
 }
 
 \cs_new:cpn { __jsonparse_parse_num_ . :w } #1 \q_stop {
-  \exp_last_unbraced:No 
+  \exp_last_unbraced:No
     \__jsonparse_parse_num_fraction:w #1 \q_stop
 }
 
 \cs_new:cpn { __jsonparse_parse_num_ e :w } #1 \q_stop {
-  \exp_last_unbraced:No 
+  \exp_last_unbraced:No
     \__jsonparse_parse_num_exponent:w #1 \q_stop
 }
 
 \cs_new:cpn { __jsonparse_parse_num_ E :w } #1 \q_stop {
-  \exp_last_unbraced:No 
+  \exp_last_unbraced:No
     \__jsonparse_parse_num_exponent:w #1 \q_stop
 }
 
 \clist_map_inline:Nn \c__jsonparse_num_digits_clist {
   \cs_new:cpn { __jsonparse_parse_num_ #1 :w } ##1 \q_stop {
-    \exp_last_unbraced:No 
+    \exp_last_unbraced:No
       \__jsonparse_parse_num_digit:w ##1 \q_stop
   }
 }
@@ -395,7 +403,7 @@
     } {
       \clist_if_in:NVT \c__jsonparse_num_others_clist \l__jsonparse_num_input_last_tl {
         \tl_set:Nn \l__jsonparse_num_remainder_tl { }
-        \bool_set_false:N \l__jsonparse_num_bool 
+        \bool_set_false:N \l__jsonparse_num_bool
       }
     }
   }
@@ -416,7 +424,7 @@
     } {
       \clist_if_in:NVT \c__jsonparse_num_others_clist \l__jsonparse_num_input_last_tl {
         \tl_set:Nn \l__jsonparse_num_remainder_tl { }
-        \bool_set_false:N \l__jsonparse_num_bool 
+        \bool_set_false:N \l__jsonparse_num_bool
       }
     }
   }
@@ -439,7 +447,7 @@
     } {
       \clist_if_in:NVT \c__jsonparse_num_others_clist \l__jsonparse_num_input_last_tl {
         \tl_set:Nn \l__jsonparse_num_remainder_tl { }
-        \bool_set_false:N \l__jsonparse_num_bool 
+        \bool_set_false:N \l__jsonparse_num_bool
       }
     }
   }
@@ -455,7 +463,7 @@
 \cs_new:Npn \__jsonparse_parse_num_digit:w #1 \q_stop {
   \bool_lazy_any:nTF {
     { \tl_if_empty_p:N \l__jsonparse_num_input_last_tl }
-    { \bool_lazy_and_p:nn 
+    { \bool_lazy_and_p:nn
       { \str_if_eq_p:Vn \l__jsonparse_num_input_last_tl { - } }
       { \bool_not_p:n { \l__jsonparse_num_exponent_seen_bool } }
     }
@@ -462,7 +470,7 @@
   } {
     \str_if_eq:enT { \tl_head:n {#1} } { 0 } {
       \bool_set_true:N \l__jsonparse_num_zero_seen_bool
-    } 
+    }
   } {
     \bool_if:NT \l__jsonparse_num_zero_seen_bool {
       \tl_set:Nn \l__jsonparse_num_remainder_tl { }
@@ -476,7 +484,7 @@
 
 \cs_new:Npn \__jsonparse_parse_num_other:w #1 \q_stop {
   \tl_set:Nn \l__jsonparse_num_remainder_tl { }
-  \bool_set_false:N \l__jsonparse_num_bool 
+  \bool_set_false:N \l__jsonparse_num_bool
 }
 
 % ===
@@ -484,28 +492,28 @@
 \cs_new_protected:Npn \jsonparse_parse_to_prop:Nn #1#2 {
   \bool_if:NT \l__jsonparse_debug_mode_bool {
     \msg_log:nne { jsonparse } { debug-info } {
-      \iow_newline: 
-      Parsing ~ JSON ~ ... 
-    } 
+      \iow_newline:
+      Parsing ~ JSON ~ ...
+    }
   }
   \prop_gclear:N \g_jsonparse_entries_prop
   \jsonparse_parse:n {#2}
-  \prop_gset_eq:NN #1 \g_jsonparse_entries_prop 
+  \prop_gset_eq:NN #1 \g_jsonparse_entries_prop
   \bool_if:NT \l__jsonparse_debug_mode_bool {
     \msg_log:nne { jsonparse } { debug-info } {
-      JSON ~ parsing ~ done. \iow_newline: 
-    } 
+      JSON ~ parsing ~ done. \iow_newline:
+    }
   }
 }
 
 \cs_new_protected:Npn \jsonparse_parse:n #1 {
   \tl_set:Ne \l__jsonparse_input_tl { \tl_trim_spaces:e {#1} }
-  \cs_if_exist_use:cTF { __jsonparse_parse_ \str_head_ignore_spaces:o { \l__jsonparse_input_tl } :w } { 
+  \cs_if_exist_use:cTF { __jsonparse_parse_ \str_head_ignore_spaces:o { \l__jsonparse_input_tl } :w } {
     \l__jsonparse_input_tl \q_stop
   } {
     % other
-    \exp_last_unbraced:No 
-      \__jsonparse_parse_other:w \l__jsonparse_input_tl \q_stop 
+    \exp_last_unbraced:No
+      \__jsonparse_parse_other:w \l__jsonparse_input_tl \q_stop
   }
 }
 
@@ -512,41 +520,41 @@
 % ===
 
 \cs_new:cpn { __jsonparse_parse_ \c_left_brace_str :w } #1 \q_stop {
-  \exp_last_unbraced:No 
+  \exp_last_unbraced:No
     \__jsonparse_parse_object_begin:w #1 \q_stop
 }
 
 \cs_new:cpn { __jsonparse_parse_ \c_right_brace_str :w } #1 \q_stop {
-  \exp_last_unbraced:No 
+  \exp_last_unbraced:No
     \__jsonparse_parse_object_end:w #1 \q_stop
 }
 
 \cs_new:cpn { __jsonparse_parse_ [ :w } #1 \q_stop {
-  \exp_last_unbraced:No 
+  \exp_last_unbraced:No
     \__jsonparse_parse_array_begin:w #1 \q_stop
 }
 
 \cs_new:cpn { __jsonparse_parse_ ] :w } #1 \q_stop {
-  \exp_last_unbraced:No 
+  \exp_last_unbraced:No
     \__jsonparse_parse_array_end:w #1 \q_stop
 }
 
 \cs_new:cpn { __jsonparse_parse_ " :w } #1 \q_stop {
-  \exp_last_unbraced:No 
+  \exp_last_unbraced:No
     \__jsonparse_parse_string_key:w #1 \q_stop
 }
 
 \cs_new:Npn \__jsonparse_array_key_set: {
-  \str_if_eq:eVT { 
-    \tl_range:Nen \l__jsonparse_prefix_tl { 
-      \int_eval:n { 
-        -1 * \tl_count:N \l__jsonparse_array_sep_left_str 
-      } 
+  \str_if_eq:eVT {
+    \tl_range:Nen \l__jsonparse_prefix_tl {
+      \int_eval:n {
+        -1 * \tl_count:N \l__jsonparse_array_sep_left_str
+      }
     } { -1 }
   } \l__jsonparse_array_sep_left_str {
     \int_incr:N \l__jsonparse_array_index_int
-    \tl_set:Ne \l__jsonparse_key_tl { 
-      \l__jsonparse_prefix_tl \int_use:N \l__jsonparse_array_index_int \l__jsonparse_array_sep_right_str 
+    \tl_set:Ne \l__jsonparse_key_tl {
+      \l__jsonparse_prefix_tl \int_use:N \l__jsonparse_array_index_int \l__jsonparse_array_sep_right_str
     }
   }
 }
@@ -558,11 +566,11 @@
     % object begin
     \bool_if:NT \l__jsonparse_debug_mode_bool {
       \msg_log:nnn { jsonparse } { debug-info } {
-        (obj ~ begin) 
-      } 
+        (obj ~ begin)
+      }
     }
     \tl_if_empty:NTF \l__jsonparse_key_tl {
-      \tl_set_eq:NN \l__jsonparse_object_array_key_tl \l__jsonparse_child_sep_str 
+      \tl_set_eq:NN \l__jsonparse_object_array_key_tl \l__jsonparse_child_sep_str
     } {
       \tl_set_eq:NN \l__jsonparse_object_array_key_tl \l__jsonparse_key_tl
       \tl_set:Ne \l__jsonparse_prefix_tl { \l__jsonparse_key_tl \l__jsonparse_child_sep_str }
@@ -572,7 +580,7 @@
 }
 
 \exp_last_unbraced:NNo \cs_new:Npn \__jsonparse_parse_object_end:w \c_right_brace_str #1 \q_stop {
-    \tl_set:Ne \l__jsonparse_object_array_val_tl { 
+    \tl_set:Ne \l__jsonparse_object_array_val_tl {
       \tl_range:Nne \l__jsonparse_object_array_val_tl { 1 } {
         \int_eval:n {
           -1 * \tl_count:n {#1} - 1
@@ -579,20 +587,20 @@
         }
       }
     }
-    \prop_gput:Nee \g_jsonparse_entries_prop 
+    \prop_gput:Nee \g_jsonparse_entries_prop
       { \l__jsonparse_object_array_key_tl } { \l__jsonparse_object_array_val_tl }
     \bool_if:NT \l__jsonparse_debug_mode_bool {
       \msg_log:nne { jsonparse } { debug-info } {
         (key) ~ \str_use:N \l__jsonparse_object_array_key_tl : \iow_newline:
-        \iow_char:N \  \iow_char:N \  (obj) ~ \str_use:N \l__jsonparse_object_array_val_tl 
-      } 
-    } 
+        \iow_char:N \  \iow_char:N \  (obj) ~ \str_use:N \l__jsonparse_object_array_val_tl
+      }
+    }
   \group_end:
   % object end
   \bool_if:NT \l__jsonparse_debug_mode_bool {
     \msg_log:nnn { jsonparse } { debug-info } {
-      (obj ~ end) 
-    } 
+      (obj ~ end)
+    }
   }
   \tl_set:Nn \l__jsonparse_remainder_tl {#1}
   \__jsonparse_parse_remainder:
@@ -605,7 +613,7 @@
     % array begin
     \bool_if:NT \l__jsonparse_debug_mode_bool {
       \msg_log:nnn { jsonparse } { debug-info } {
-        (arr ~ begin) 
+        (arr ~ begin)
       }
     }
     \int_zero:N \l__jsonparse_array_index_int
@@ -619,7 +627,7 @@
 }
 
 \cs_new:Npn \__jsonparse_parse_array_end:w ] #1 \q_stop {
-    \tl_set:Ne \l__jsonparse_object_array_val_tl { 
+    \tl_set:Ne \l__jsonparse_object_array_val_tl {
       \tl_range:Nne \l__jsonparse_object_array_val_tl { 1 } {
         \int_eval:n {
           -1 * \tl_count:n {#1} - 1
@@ -626,20 +634,20 @@
         }
       }
     }
-    \prop_gput:Nee \g_jsonparse_entries_prop 
+    \prop_gput:Nee \g_jsonparse_entries_prop
       { \l__jsonparse_object_array_key_tl } { \l__jsonparse_object_array_val_tl }
     \bool_if:NT \l__jsonparse_debug_mode_bool {
       \msg_log:nne { jsonparse } { debug-info } {
         (key) ~ \str_use:N \l__jsonparse_object_array_key_tl : \iow_newline:
         \iow_char:N \  \iow_char:N \  (arr) ~ \str_use:N \l__jsonparse_object_array_val_tl
-      } 
-    } 
+      }
+    }
   \group_end:
   % array end
   \bool_if:NT \l__jsonparse_debug_mode_bool {
     \msg_log:nnn { jsonparse } { debug-info } {
-      (arr ~ end) 
-    } 
+      (arr ~ end)
+    }
   }
   \tl_set:Nn \l__jsonparse_remainder_tl {#1}
   \__jsonparse_parse_remainder:
@@ -650,11 +658,11 @@
   \tl_set:Ne \l__jsonparse_remainder_tl { \tl_trim_spaces:n {#2} }
   % key or string?
   \tl_if_head_eq_charcode:oNTF { \l__jsonparse_remainder_tl } : {
-    \tl_remove_once:NV \l__jsonparse_remainder_tl \c_colon_str 
+    \tl_remove_once:NV \l__jsonparse_remainder_tl \c_colon_str
     \tl_set:Ne \l__jsonparse_key_tl { \l__jsonparse_prefix_tl #1 }
   } {
     \tl_set:Nn \l__jsonparse_val_tl {#1}
-    \prop_gput:Nee \g_jsonparse_entries_prop 
+    \prop_gput:Nee \g_jsonparse_entries_prop
       { \l__jsonparse_key_tl } { \l__jsonparse_val_tl }
     % string
     \bool_if:NT \l__jsonparse_debug_mode_bool {
@@ -661,7 +669,7 @@
       \msg_log:nne { jsonparse } { debug-info } {
         (key) ~ \str_use:N \l__jsonparse_key_tl : \iow_newline:
         \iow_char:N \  \iow_char:N \  (str) ~ \str_use:N \l__jsonparse_val_tl
-      } 
+      }
     }
   }
   \__jsonparse_parse_remainder:
@@ -681,9 +689,9 @@
   \tl_set:Ne \l__jsonparse_temp_tl { \tl_trim_spaces:n {#1} }
   \cs_if_exist_use:cF { __jsonparse_parse_ \str_casefold:o { \l__jsonparse_temp_tl } : } {
     \bool_if:NTF \l__jsonparse_check_num_bool {
-      \jsonparse_if_num:nTF {#1} { 
+      \jsonparse_if_num:nTF {#1} {
         \tl_set:Nn \l__jsonparse_val_tl {#1}
-        \prop_gput:Nee \g_jsonparse_entries_prop 
+        \prop_gput:Nee \g_jsonparse_entries_prop
           { \l__jsonparse_key_tl } { \l__jsonparse_val_tl }
         % number
         \bool_if:NT \l__jsonparse_debug_mode_bool {
@@ -690,16 +698,16 @@
           \msg_log:nne { jsonparse } { debug-info } {
             (key) ~ \str_use:N \l__jsonparse_key_tl : \iow_newline:
             \iow_char:N \  \iow_char:N \  (num) ~ \str_use:N \l__jsonparse_val_tl
-          } 
+          }
         }
-      } { 
+      } {
         % not a valid JSON fp
         \msg_error:nnoo { jsonparse } { parsing-error }
           { \l__jsonparse_key_tl } {#1}
-      } 
+      }
     } {
       \tl_set:Nn \l__jsonparse_val_tl {#1}
-      \prop_gput:Nee \g_jsonparse_entries_prop 
+      \prop_gput:Nee \g_jsonparse_entries_prop
         { \l__jsonparse_key_tl } { \l__jsonparse_val_tl }
       % number
       \bool_if:NT \l__jsonparse_debug_mode_bool {
@@ -706,15 +714,15 @@
         \msg_log:nne { jsonparse } { debug-info } {
           (key) ~ \str_use:N \l__jsonparse_key_tl : \iow_newline:
           \iow_char:N \  \iow_char:N \  (num) ~ \str_use:N \l__jsonparse_val_tl
-        } 
+        }
       }
     }
   }
   \tl_set:Ne \l__jsonparse_remainder_tl { \tl_trim_spaces:e { \l__jsonparse_remainder_tl } }
-  \tl_set:Ne \l__jsonparse_remainder_tl { 
-    \tl_range:Nen \l__jsonparse_remainder_tl { 
+  \tl_set:Ne \l__jsonparse_remainder_tl {
+    \tl_range:Nen \l__jsonparse_remainder_tl {
       \int_eval:n {
-        \tl_count:n {#1} + 1 
+        \tl_count:n {#1} + 1
       }
     } { -1 }
   }
@@ -722,8 +730,8 @@
 }
 
 \cs_new:Npn \__jsonparse_parse_true: {
-  \tl_set_eq:NN \l__jsonparse_val_tl \l__jsonparse_true_str 
-  \prop_gput:Nee \g_jsonparse_entries_prop 
+  \tl_set_eq:NN \l__jsonparse_val_tl \l__jsonparse_true_str
+  \prop_gput:Nee \g_jsonparse_entries_prop
     { \l__jsonparse_key_tl } { \l__jsonparse_val_tl }
   % true
   \bool_if:NT \l__jsonparse_debug_mode_bool {
@@ -730,13 +738,13 @@
     \msg_log:nne { jsonparse } { debug-info } {
       (key) ~ \str_use:N \l__jsonparse_key_tl : \iow_newline:
       \iow_char:N \  \iow_char:N \  (tru) ~ \str_use:N \l__jsonparse_val_tl
-    } 
+    }
   }
 }
 
 \cs_new:Npn \__jsonparse_parse_false: {
-  \tl_set_eq:NN \l__jsonparse_val_tl \l__jsonparse_false_str 
-  \prop_gput:Nee \g_jsonparse_entries_prop 
+  \tl_set_eq:NN \l__jsonparse_val_tl \l__jsonparse_false_str
+  \prop_gput:Nee \g_jsonparse_entries_prop
     { \l__jsonparse_key_tl } { \l__jsonparse_val_tl }
   % false
   \bool_if:NT \l__jsonparse_debug_mode_bool {
@@ -743,13 +751,13 @@
     \msg_log:nne { jsonparse } { debug-info } {
       (key) ~ \str_use:N \l__jsonparse_key_tl : \iow_newline:
       \iow_char:N \  \iow_char:N \  (fal) ~ \str_use:N \l__jsonparse_val_tl
-    } 
+    }
   }
 }
 
 \cs_new:Npn \__jsonparse_parse_null: {
   \tl_set_eq:NN \l__jsonparse_val_tl \l__jsonparse_null_str
-  \prop_gput:Nee \g_jsonparse_entries_prop 
+  \prop_gput:Nee \g_jsonparse_entries_prop
     { \l__jsonparse_key_tl } { \l__jsonparse_val_tl }
   % null
   \bool_if:NT \l__jsonparse_debug_mode_bool {
@@ -756,7 +764,7 @@
     \msg_log:nne { jsonparse } { debug-info } {
       (key) ~ \str_use:N \l__jsonparse_key_tl : \iow_newline:
       \iow_char:N \  \iow_char:N \  (nul) ~ \str_use:N \l__jsonparse_val_tl
-    } 
+    }
   }
 }
 
@@ -773,16 +781,16 @@
 \cs_new_protected:Npn \jsonparse_filter:Nn #1#2 {
   \prop_clear:N \l__jsonparse_temp_prop
   \prop_map_inline:Nn #1 {
-    \str_case_e:en { 
-      \tl_range:nne {##1} { 1 } { \int_eval:n { \tl_count:n {#2} + 1 } } 
+    \str_case_e:en {
+      \tl_range:nne {##1} { 1 } { \int_eval:n { \tl_count:n {#2} + 1 } }
     } {
       { #2 \l__jsonparse_child_sep_str } {
-        \prop_put:Nen \l__jsonparse_temp_prop 
-          { \tl_range:nen {##1} { \int_eval:n { \tl_count:n {#2} + 2 } } { -1 } } {##2} 
+        \prop_put:Nen \l__jsonparse_temp_prop
+          { \tl_range:nen {##1} { \int_eval:n { \tl_count:n {#2} + 2 } } { -1 } } {##2}
       }
       { #2 \l__jsonparse_array_sep_left_str } {
-        \prop_put:Nen \l__jsonparse_temp_prop 
-          { \tl_range:nen {##1} { \int_eval:n { \tl_count:n {#2} + 1 } } { -1 } } {##2} 
+        \prop_put:Nen \l__jsonparse_temp_prop
+          { \tl_range:nen {##1} { \int_eval:n { \tl_count:n {#2} + 1 } } { -1 } } {##2}
       }
     }
   }
@@ -793,8 +801,8 @@
 
 \NewDocumentCommand { \JSONParsePut } { m m +v } {
   \prop_if_exist:NF #1 {
-    \prop_new:N #1 
-  } 
+    \prop_new:N #1
+  }
   \prop_gput:Nnn #1 {#2} {#3}
 }
 
@@ -828,7 +836,7 @@
   \group_begin:
     \str_set:Ne \l_jsonparse_current_prop_str { \cs_to_str:N #2 }
     \keys_set_known:nnN { jsonparse / global } {#1} \l__jsonparse_unused_keys_clist
-    \keys_set_known:noN { jsonparse / parse } { \l__jsonparse_unused_keys_clist } \l__jsonparse_unused_keys_clist 
+    \keys_set_known:noN { jsonparse / parse } { \l__jsonparse_unused_keys_clist } \l__jsonparse_unused_keys_clist
     \__jsonparse_warning_unused_keys:
     \bool_set_false:N \l__jsonparse_externalize_load_bool
     \bool_if:NT \l__jsonparse_externalize_bool {
@@ -855,8 +863,8 @@
         \cs_set:Npn \u { \exp_not:N \u }
         \__json_nested_construct_cs:Noo \x \c_left_brace_str \c_right_brace_str
         \tl_set:Nn \obeyedline { ~ }
-        \tl_gset_rescan:Nne \g__jsonparse_json_tl { \cctab_select:N \c__jsonparse_json_escape_cctab } {#3} 
-        \exp_args:NNe \jsonparse_parse_to_prop:Nn #2 { \g__jsonparse_json_tl } 
+        \tl_gset_rescan:Nne \g__jsonparse_json_tl { \cctab_select:N \c__jsonparse_json_escape_cctab } {#3}
+        \exp_args:NNe \jsonparse_parse_to_prop:Nn #2 { \g__jsonparse_json_tl }
       \group_end:
       \bool_if:NT \l__jsonparse_externalize_bool {
         \__jsonparse_externalize:Nn #2 { \l__jsonparse_externalize_file_name_tl .jsonparse }
@@ -873,8 +881,8 @@
   \group_begin:
     \str_set:Ne \l_jsonparse_current_prop_str { \cs_to_str:N #2 }
     \keys_set_known:nnN { jsonparse / global } {#1} \l__jsonparse_unused_keys_clist
-    \keys_set_known:noN { jsonparse / parse } { \l__jsonparse_unused_keys_clist } \l__jsonparse_unused_keys_clist 
-    \__jsonparse_warning_unused_keys: 
+    \keys_set_known:noN { jsonparse / parse } { \l__jsonparse_unused_keys_clist } \l__jsonparse_unused_keys_clist
+    \__jsonparse_warning_unused_keys:
     \bool_set_false:N \l__jsonparse_externalize_load_bool
     \bool_if:NT \l__jsonparse_externalize_bool {
       \file_if_exist:eT { \l__jsonparse_externalize_file_name_tl .jsonparse } {
@@ -899,7 +907,7 @@
         \cs_set:Npn \t { \exp_not:N \t }
         \cs_set:Npn \u { \exp_not:N \u }
         \file_get:nnN {#3} { \cctab_select:N \c__jsonparse_json_escape_cctab } \g__jsonparse_json_tl
-        \exp_args:NNe \jsonparse_parse_to_prop:Nn #2 { \g__jsonparse_json_tl } 
+        \exp_args:NNe \jsonparse_parse_to_prop:Nn #2 { \g__jsonparse_json_tl }
       \group_end:
       \bool_if:NT \l__jsonparse_externalize_bool {
         \__jsonparse_externalize:Nn #2 { \l__jsonparse_externalize_file_name_tl .jsonparse }
@@ -909,7 +917,7 @@
 }
 
 \NewExpandableDocumentCommand { \JSONParseExpandableValue } { m m } {
-  \prop_item:Ne #1 {#2} 
+  \prop_item:Ne #1 {#2}
 }
 
 \cs_set_eq:NN \__jsonparse_tex_quote: \"
@@ -932,7 +940,7 @@
     \cs_set_eq:NN \u \__jsonparse_unicode_char:NNNN
     \tl_set:Ne \l__jsonparse_temp_tl {#1}
     \cs_set_eq:NN \" \__jsonparse_tex_quote:
-    \cs_set_eq:NN \\ \__jsonparse_tex_backslash: 
+    \cs_set_eq:NN \\ \__jsonparse_tex_backslash:
     \bool_if:NT \l__jsonparse_escape_number_sign_bool {
       \tl_replace_all:Noe \l__jsonparse_temp_tl { \c_hash_str } { \c_backslash_str \c_hash_str }
     }
@@ -963,7 +971,7 @@
     \keys_set_known:nn { jsonparse / typeset } {#1} \l__jsonparse_unused_keys_clist
     \__jsonparse_warning_unused_keys:
     \bool_if:NTF \l__jsonparse_rescan_bool {
-      \exp_args:Ne \__jsonparse_rescan:n { \prop_item:Ne #2 {#3} } 
+      \exp_args:Ne \__jsonparse_rescan:n { \prop_item:Ne #2 {#3} }
     } {
       \prop_item:Ne #2 {#3}
     }
@@ -977,93 +985,232 @@
   \bool_set_true:N \l__jsonparse_prop_map_first_bool
   \tl_set:Nn \l__jsonparse_temp_tl { [ }
     \prop_map_inline:Nn #1 {
-      \tl_if_in:nVF {##1} \l__jsonparse_child_sep_str { 
-        \bool_if:NTF \l__jsonparse_prop_map_first_bool { 
+      \tl_if_in:nVF {##1} \l__jsonparse_child_sep_str {
+        \bool_if:NTF \l__jsonparse_prop_map_first_bool {
           \bool_set_false:N \l__jsonparse_prop_map_first_bool
         } {
-          \tl_put_right:Nn \l__jsonparse_temp_tl { , } 
+          \tl_put_right:Nn \l__jsonparse_temp_tl { , }
         }
         \tl_put_right:Nn \l__jsonparse_temp_tl { " ##1 " }
       }
     }
-  \tl_put_right:Nn \l__jsonparse_temp_tl { ] } 
+  \tl_put_right:Nn \l__jsonparse_temp_tl { ] }
   \tl_set_eq:NN #2 \l__jsonparse_temp_tl
 }
 
-\NewDocumentCommand { \JSONParseArrayValues } { O{} m m O{} m } {
+\cs_new:Npn \__jsonparse_get_array_index:w [ #1 ] #2 \q_stop {
+  #1
+}
+
+\cs_new_protected:Npn \jsonparse_array_count:NN #1#2 {
+  \int_zero:N #2
+  \int_set:Nn \l__jsonparse_array_count_last_int { -1 }
+  \prop_map_inline:Nn #1 {
+    \str_if_eq:eVF { \tl_head:n {##1} } \l__jsonparse_array_sep_left_str {
+			\msg_error:nnn { jsonparse } { not-array-item }
+		  	{##1}
+		}
+    \int_compare:nNnF {
+      \__jsonparse_get_array_index:w ##1 \q_stop
+    } = { \l__jsonparse_array_count_last_int } {
+      \int_incr:N #2
+    }
+    \int_set:Nn \l__jsonparse_array_count_last_int {
+      \__jsonparse_get_array_index:w ##1 \q_stop
+    }
+  }
+}
+
+\NewDocumentCommand { \JSONParseArrayCount } { m m } {
   \group_begin:
+    \tl_set:Nn \l__jsonparse_temp_tl {#1}
+    \jsonparse_filter:Nn \l__jsonparse_temp_tl {#2}
+    \jsonparse_array_count:NN \l__jsonparse_temp_tl \l__jsonparse_array_count_int
+    \int_use:N \l__jsonparse_array_count_int
+  \group_end:
+}
+
+\NewDocumentCommand { \JSONParseArrayValues } { O{} m m o m } {
+  \group_begin:
     \keys_set_known:nn { jsonparse / typeset } {#1} \l__jsonparse_unused_keys_clist
     \__jsonparse_warning_unused_keys:
     \tl_set:Nn \l__jsonparse_temp_tl {#2}
     \jsonparse_filter:Nn \l__jsonparse_temp_tl {#3}
-    \bool_set_true:N \l__jsonparse_prop_map_first_bool
-    \prop_map_inline:Nn \l__jsonparse_temp_tl {
-      \str_if_eq:enT { 
-        \tl_range:nen {##1} { \int_eval:n { -1 * \tl_count:n {#4} } } { -1 } 
-      } {#4} {
-        \bool_if:NTF \l__jsonparse_prop_map_first_bool { 
-          \bool_set_false:N \l__jsonparse_prop_map_first_bool
-        } {
-          #5 
+    \jsonparse_array_count:NN \l__jsonparse_temp_tl \l__jsonparse_array_count_int
+    \bool_set_true:N \l__jsonparse_prop_map_first_bool	
+    \int_step_inline:nn { \l__jsonparse_array_count_int } {
+      \bool_if:NTF \l__jsonparse_prop_map_first_bool {
+        \bool_set_false:N \l__jsonparse_prop_map_first_bool
+      } {
+        #5
+      }
+      \bool_if:NTF \l__jsonparse_rescan_bool {
+        \exp_args:Ne \__jsonparse_rescan:n {
+          \prop_item:Ne \l__jsonparse_temp_tl {
+            \l__jsonparse_array_sep_left_str
+            \bool_if:NTF \l__jsonparse_zero_based_bool {
+              \int_eval:n { ##1 - 1 }
+            } {
+              ##1
+            }
+            \l__jsonparse_array_sep_right_str
+            \IfValueT {#4} {
+              \l__jsonparse_child_sep_str
+              #4
+            }
+          }
         }
-        \bool_if:NTF \l__jsonparse_rescan_bool {
-          \__jsonparse_rescan:n {##2}
-        } {
-          ##2 
+      } {
+        \prop_item:Ne \l__jsonparse_temp_tl {
+          \l__jsonparse_array_sep_left_str
+          \bool_if:NTF \l__jsonparse_zero_based_bool {
+            \int_eval:n { ##1 - 1 }
+          } {
+            ##1
+          }
+          \l__jsonparse_array_sep_right_str
+          \IfValueT {#4} {
+            \l__jsonparse_child_sep_str
+            #4
+          }
         }
-      } 
+      }
     }
   \group_end:
 }
 
-\cs_new:Npn \__jsonparse_get_array_index:w [ #1 ] #2 \q_stop {
-  #1
-}
-
-\NewDocumentCommand { \JSONParseArrayCount } { m m } {
-  \group_begin:
-    \jsonparse_filter:Nn #1 {#2}
-    \int_zero:N \l__jsonparse_array_count_int
-    \int_set:Nn \l__jsonparse_array_count_last_int { -1 }
-    \prop_map_inline:Nn #1 {
-      \int_compare:nNnF { 
-        \__jsonparse_get_array_index:w ##1 \q_stop 
-      } = { \l__jsonparse_array_count_last_int } {
-        \int_incr:N \l__jsonparse_array_count_int
-      }
-      \int_set:Nn \l__jsonparse_array_count_last_int {
-        \__jsonparse_get_array_index:w ##1 \q_stop
-      }
-    } 
-    \int_use:N \l__jsonparse_array_count_int
-  \group_end:
-}
-
-\tl_new:N \JSONParseArrayIndex 
-\tl_new:N \JSONParseArrayKey 
+\tl_new:N \JSONParseArrayNewline
+\tl_new:N \JSONParseArrayIndex
+\tl_new:N \JSONParseArrayKey
 \tl_new:N \JSONParseArrayValue
 
-\NewDocumentCommand { \JSONParseArrayValuesMap } { O{} m m O{} m } {
-  \group_begin:
+\NewDocumentCommand { \JSONParseArrayValuesMap } { O{} m m o m O{} O{} } {
+	\group_begin:
     \keys_set_known:nn { jsonparse / typeset } {#1} \l__jsonparse_unused_keys_clist
     \__jsonparse_warning_unused_keys:
-    \jsonparse_filter:Nn #2 {#3}
-    \prop_map_inline:Nn #2 {
-      \str_if_eq:enT { 
-        \tl_range:nen {##1} { \int_eval:n { -1 * \tl_count:n {#4} } } { -1 } 
-      } {#4} {
-        \int_incr:N \l__jsonparse_array_index_int
-        \tl_set:Ne \JSONParseArrayIndex { \__jsonparse_get_array_index:w ##1 \q_stop }
-        \tl_set:Nn \JSONParseArrayKey {##1}
+    \tl_set:Nn \l__jsonparse_temp_tl {#2}
+    \jsonparse_filter:Nn \l__jsonparse_temp_tl {#3}
+    \jsonparse_array_count:NN \l__jsonparse_temp_tl \l__jsonparse_array_count_int
+    \IfValueT {#4} {
+      \int_zero:N \l__jsonparse_array_keys_index_int
+      \clist_map_inline:nn {#4} {
+        \int_incr:N \l__jsonparse_array_keys_index_int
+        \tl_set:Ne \l__jsonparse_array_keys_index_roman_tl {
+          \int_to_Roman:n { \l__jsonparse_array_keys_index_int }
+        }
+        \tl_if_exist:cF { JSONParseArrayKey \l__jsonparse_array_keys_index_roman_tl } {
+          \tl_new:c { JSONParseArrayKey \l__jsonparse_array_keys_index_roman_tl }
+        }
+        \tl_if_exist:cF { JSONParseArrayValue \l__jsonparse_array_keys_index_roman_tl } {
+          \tl_new:c { JSONParseArrayValue \l__jsonparse_array_keys_index_roman_tl }
+        }
+      }
+    }
+    #6
+    \tl_gset:Nn \JSONParseArrayNewline { \tabularnewline }
+    \int_step_inline:nn { \l__jsonparse_array_count_int } {
+      \bool_if:NTF \l__jsonparse_zero_based_bool {
+        \tl_gset:Nn \JSONParseArrayIndex { \int_eval:n { ##1 - 1 } }
+      } {
+        \tl_gset:Nn \JSONParseArrayIndex {##1}
+      }
+      \IfValueTF {#4} {
+        \int_zero:N \l__jsonparse_array_keys_index_int
+        \clist_map_inline:nn {#4} {
+          \int_incr:N \l__jsonparse_array_keys_index_int
+          \tl_set:Ne \l__jsonparse_array_keys_index_roman_tl {
+            \int_to_Roman:n { \l__jsonparse_array_keys_index_int }
+          }
+          \tl_gset:ce { JSONParseArrayKey \l__jsonparse_array_keys_index_roman_tl } {
+            \l__jsonparse_array_sep_left_str
+            \bool_if:NTF \l__jsonparse_zero_based_bool {
+              \int_eval:n { ##1 - 1 }
+            } {
+              ##1
+            }
+            \l__jsonparse_array_sep_right_str
+            \l__jsonparse_child_sep_str
+            ####1
+          }
+          \bool_if:NTF \l__jsonparse_rescan_bool {
+            \tl_gset:cn { JSONParseArrayValue \l__jsonparse_array_keys_index_roman_tl } {
+              \exp_args:Ne \__jsonparse_rescan:n {
+                \prop_item:Ne \l__jsonparse_temp_tl {
+                  \l__jsonparse_array_sep_left_str
+                  \bool_if:NTF \l__jsonparse_zero_based_bool {
+                    \int_eval:n { ##1 - 1 }
+                  } {
+                    ##1
+                  }
+                  \l__jsonparse_array_sep_right_str
+                  \l__jsonparse_child_sep_str
+                  ####1
+                }
+              }
+            }
+          } {
+            \tl_gset:ce { JSONParseArrayValue \l__jsonparse_array_keys_index_roman_tl } {
+              \prop_item:Ne \l__jsonparse_temp_tl {
+                \l__jsonparse_array_sep_left_str
+                \bool_if:NTF \l__jsonparse_zero_based_bool {
+                  \int_eval:n { ##1 - 1 }
+                } {
+                  ##1
+                }
+                \l__jsonparse_array_sep_right_str
+                \l__jsonparse_child_sep_str
+                ####1
+              }
+            }
+          }
+        }
+        \tl_gset_eq:NN \JSONParseArrayKey \JSONParseArrayKeyI
+        \tl_gset_eq:NN \JSONParseArrayValue \JSONParseArrayValueI
+      } {
+        \tl_gset:Ne \JSONParseArrayKey {
+          \l__jsonparse_array_sep_left_str
+          \bool_if:NTF \l__jsonparse_zero_based_bool {
+            \int_eval:n { ##1 - 1 }
+          } {
+            ##1
+          }
+          \l__jsonparse_array_sep_right_str
+        }
         \bool_if:NTF \l__jsonparse_rescan_bool {
-          \tl_set:Nn \JSONParseArrayValue { \exp_args:Ne \__jsonparse_rescan:n { \prop_item:Nn #2 {##1} } }
+          \tl_gset:Nn \JSONParseArrayValue {
+            \exp_args:Ne \__jsonparse_rescan:n {
+              \prop_item:Ne \l__jsonparse_temp_tl {
+                \l__jsonparse_array_sep_left_str
+                \bool_if:NTF \l__jsonparse_zero_based_bool {
+                  \int_eval:n { ##1 - 1 }
+                } {
+                  ##1
+                }
+                \l__jsonparse_array_sep_right_str
+              }
+            }
+          }
         } {
-          \tl_set:Nn \JSONParseArrayValue { \prop_item:Nn #2 {##1} }
+          \tl_gset:Ne \JSONParseArrayValue {
+            \prop_item:Ne \l__jsonparse_temp_tl {
+              \l__jsonparse_array_sep_left_str
+              \bool_if:NTF \l__jsonparse_zero_based_bool {
+                \int_eval:n { ##1 - 1 }
+              } {
+                ##1
+              }
+              \l__jsonparse_array_sep_right_str
+            }
+          }
         }
-        \use:c {#5} 
       }
-    } 
-  \group_end:
+      \int_compare:nNnT {##1} = { \l__jsonparse_array_count_int } {
+        \tl_gset:Nn \JSONParseArrayNewline { }
+      }
+      \use:c {#5}
+    }
+    #7
+	\group_end:
 }
 
 % EOF



More information about the tex-live-commits mailing list.