文章目录
更新内容
新增方法
getKeys
获取属性名列表,返回属性个数
n_json ljson
string ls_key_list[]
long ll_key_count
ljson = create n_json
ljson.parse('{"itemCode":"0001","itemName":"PowerBuilder","sequence":1}')
//获取属性名列表
ll_key_count = ljson.getKeys(ls_key_list)
return 0
extend
将目标json的属性并入当前json
n_json ljson,ljson_other
string ls
ljson = create n_json
ljson.parse('{"itemCode":"0001","itemName":"PowerBuilder","sequence":1}')
ljson_other = create n_json
ljson_other.parse('{"itemClass":"Programming","status":"1"}')
//将目标json的属性并入当前json
ljson.extend(ljson_other)
ls = ljson.stringify()
return 0
setSQL、setSQLRow
将SQL检索出结果集后转json
测试表数据检索如下:
测试setSQL代码:
n_json ljson
string ls_sql,ls
ls_sql = "select employee_id emp_id, "+&
" first_name||' '||last_name emp_name, "+&
" decode(gender,'M','Male','F','Female','Unknown') gender, "+&
" email email "+&
" from tbl_employee "
ljson = create n_json
//设置SQL结果集
ljson.setSQL('employees',ls_sql)
ljson.pretty_stringify = true
ls = ljson.stringify()
return 0
测试SQL语句执行结果如下:
代码执行效果:
测试setSQLRow代码:
n_json ljson
string ls_sql,ls
ls_sql = "select first_name,last_name,gender,email from tbl_employee where employee_id = 1 "
ljson = create n_json
//设置SQL单行结果
ljson.setSQLRow(ls_sql,1)
ljson.pretty_stringify = true
ls = ljson.stringify()
return 0
测试SQL语句执行结果如下:
代码执行效果:
修改方法
hasItem
原方法名contains改为hasItem,判定属性当前json对象中是否存在
stringify
原方法名getFormat改为stringify,内部方法重写,提升效率
修改属性
pretty_stringify
原属性名pretty_print改为pretty_stringify,转字符串是否填充换行符、制表符
源代码
代码拷贝到文本编辑器,另存为 n_json.sru,导入pbl
发现BUG请留言或私信,以便修正(QQ:768310524 TEL:18649713925)
PB12.5版本
$PBExportHeader$n_json.sru
forward
global type n_json from nonvisualobject
end type
type st_item from structure within n_json
end type
type st_name_exp from structure within n_json
end type
type st_data_col from structure within n_json
end type
end forward
type st_item from structure
string name
any value
end type
type st_name_exp from structure
string name
boolean islist
long idx_begin
long idx_end
end type
type st_data_col from structure
string colname
string coltype
string attrname
end type
global type n_json from nonvisualobject
event readme ( )
end type
global n_json n_json
type variables
private:
string items_idx='|' // |item1:1|item2:2|
st_item item_list[]
string jsonstr
char jsonc[]
long idx,jsonlen
public:
string date_format = 'yyyy-mm-dd'
string time_format = 'hh:mm:ss'
string datetime_format = 'yyyy-mm-dd hh:mm:ss'
string item_name_style = '' // STYLE_LOWER STYLE_UPPER STYLE_CAMEL STYLE_PASCAL
boolean pretty_stringify
constant string STYLE_LOWER = 'STYLE_LOWER'
constant string STYLE_UPPER = 'STYLE_UPPER'
constant string STYLE_CAMEL = 'STYLE_CAMEL'
constant string STYLE_PASCAL = 'STYLE_PASCAL'
end variables
forward prototypes
public subroutine reset ()
public function any getitem (string item_name)
public function integer delitem (string item_name)
public function integer setdata (string item_name, any data)
public function integer setdatarow (any data, long row)
public function integer setdatarow (string item_name, any data, long row)
private function integer _get_idx (string item_name)
private function string _trans_name (string item_name)
public function integer setdatarow (string item_name, any data, long begin_row, long end_row)
private subroutine _skip ()
private function integer _parse_list (ref any value[])
private function integer _parse_value (ref any value)
private subroutine _regenerate_items_idx ()
public function integer setitem (string item_name, any item_value)
public function long exportdatarow (any data)
public function long exportdata (string item_name, any data)
private function integer _parse_json (n_json ajson)
private function date _to_date (string s)
private function time _to_time (string s)
private function datetime _to_datetime (string s)
public function long getlistjson (string item_name, ref n_json rjson[])
public function any getitempath (string item_path)
private function integer _parse_expression (string expression, ref st_name_exp rst_name_exp)
public function any getitemexp (string item_expression)
public function integer rename (string item_name, string new_name)
private function integer _trans_list (ref any value[])
private function integer _trans_value (ref any value)
public function integer parse (string s)
private function boolean _check_spc (character c)
public function long getkeys (ref string keys[])
public function integer _get_data_col (any data, ref st_data_col data_col[])
private function integer _trans_data_row (any data, long row, st_data_col data_col[], ref st_item rst_item[])
public function integer extend (n_json ajson)
public function string stringify ()
public subroutine _stringify_json (n_json ajson, integer level)
public subroutine _stringify_list (n_json ajson, any value[], integer level)
public subroutine _stringify_value (n_json ajson, any value, integer level)
public subroutine _fill_jsonc (string s)
public function integer setsql (string item_name, string sql)
public function integer setsqlrow (string sql, long row)
public function boolean hasitem (string item_name)
public function integer setsqlrow (string item_name, string sql, long row)
public function integer setsqlrow (string item_name, string sql, long begin_row, long end_row)
public function long _sql_to_ds (string sql, ref datastore ds)
end prototypes
public subroutine reset ();st_item lst_items[]
char lc[]
item_list = lst_items
items_idx = '|'
jsonstr = ''
jsonc = lc
idx = 0
jsonlen = 0
end subroutine
public function any getitem (string item_name);any la_item_value
int i
setnull(la_item_value)
i = _get_idx(item_name)
if i > 0 then la_item_value = item_list[i].value
return la_item_value
end function
public function integer delitem (string item_name);int li_idx,i
st_item lst_items[]
li_idx = _get_idx(item_name)
if li_idx < 1 then return -1
for i = 1 to li_idx - 1
lst_items[i] = item_list[i]
next
for i = li_idx + 1 to upperbound(item_list)
lst_items[i - 1] = item_list[i]
next
item_list = lst_items
_regenerate_items_idx()
return 0
end function
public function integer setdata (string item_name, any data);return setdatarow(item_name,data,1,data.dynamic rowcount())
end function
public function integer setdatarow (any data, long row);long i
st_data_col lst_col[]
st_item lst_item[]
if _get_data_col(data,lst_col) < 0 then return -1
if _trans_data_row(data,row,lst_col,lst_item) < 0 then return -1
for i = 1 to upperbound(lst_item)
item_list[upperbound(item_list) + 1] = lst_item[i]
next
_regenerate_items_idx()
return 0
end function
public function integer setdatarow (string item_name, any data, long row);n_json ljson
ljson = create n_json
ljson.date_format = date_format
ljson.time_format = time_format
ljson.datetime_format = datetime_format
ljson.item_name_style = item_name_style
ljson.pretty_stringify = pretty_stringify
ljson.setdatarow(data,row)
return setitem(item_name,ljson)
end function
private function integer _get_idx (string item_name);long ll_pos1,ll_pos2
ll_pos1 = pos(items_idx,'|'+item_name+':')
if ll_pos1 < 1 then return -1
ll_pos1 += len(item_name) + 2
ll_pos2 = pos(items_idx,'|',ll_pos1+1)
return integer(mid(items_idx, ll_pos1, ll_pos2 - ll_pos1))
end function
private function string _trans_name (string item_name);string ls_name
char lc[],lc_name[]
long i,j
boolean lb_trans_flag
//命名规则转换
choose case item_name_style //user_name
case STYLE_UPPER //USER_NAME
ls_name = upper(item_name)
case STYLE_LOWER //user_name
ls_name = lower(item_name)
case STYLE_CAMEL //userName
lc = item_name
for i = 1 to upperbound(lc)
if lc[i] = '_' then
lb_trans_flag = true
continue
end if
j ++
if lb_trans_flag then
lc_name[j] = upper(string(lc[i]))
lb_trans_flag = false
else
lc_name[j] = lower(string(lc[i]))
end if
next
ls_name = lc_name
case STYLE_PASCAL //UserName
lc = item_name
lb_trans_flag = true
for i = 1 to upperbound(lc)
if lc[i] = '_' then
lb_trans_flag = true
continue
end if
j ++
if lb_trans_flag then
lc_name[j] = upper(string(lc[i]))
lb_trans_flag = false
else
lc_name[j] = lower(string(lc[i]))
end if
next
ls_name = lc_name
case else
return item_name
end choose
return ls_name
end function
public function integer setdatarow (string item_name, any data, long begin_row, long end_row);long i,j
n_json ljson_list[]
st_data_col lst_col[]
st_item lst_item[],lst_null[]
if _get_data_col(data,lst_col) < 0 then return -1
for i = begin_row to end_row
lst_item = lst_null
if _trans_data_row(data,i,lst_col,lst_item) < 0 then return -1
j += 1
ljson_list[j] = create n_json
ljson_list[j].date_format = date_format
ljson_list[j].time_format = time_format
ljson_list[j].datetime_format = datetime_format
ljson_list[j].item_name_style = item_name_style
ljson_list[j].pretty_stringify = pretty_stringify
ljson_list[j].item_list = lst_item
ljson_list[j]._regenerate_items_idx()
next
return setitem(item_name,ljson_list)
end function
private subroutine _skip ();char c
do
idx += 1
c = jsonc[idx]
loop while _check_spc(c)
end subroutine
private function integer _parse_list (ref any value[]);long i
any la_list[],la_value_list[]
_skip()
do until jsonc[idx] = ']'
i += 1
if _parse_value(la_list[i]) < 0 then return -1
_skip()
if jsonc[idx] = ',' then _skip()
loop
value = la_list
return 0
end function
private function integer _parse_value (ref any value);string ls_value
n_json ljson
any la_value,la_list[]
long ll_pos
long i
char lc_value[]
choose case jsonc[idx]
case '{'
ljson = create n_json
if _parse_json(ljson) < 0 then return -1
la_value = ljson
case '['
if _parse_list(la_list) < 0 then return -1
la_value = la_list
case '"'
idx += 1
do until jsonc[idx] = '"' or idx > jsonlen
if jsonc[idx] = '\' then
idx += 1
if not (jsonc[idx] = '"' or jsonc[idx] = '\') then
i ++
choose case jsonc[idx]
case 't'
lc_value[i] = '~t'
case 'r'
lc_value[i] = '~r'
case 'n'
lc_value[i] = '~n'
case 'f'
lc_value[i] = '~f'
case 'b'
lc_value[i] = '~b'
case 'u'
lc_value[i] = '\'
i ++
lc_value[i] = jsonc[idx]
case else
return -1
end choose
idx += 1
continue
end if
end if
i ++
lc_value[i] = jsonc[idx]
idx += 1
loop
ls_value = lc_value
la_value = ls_value
case '0' to '9','+','-',&
't','f',&
'n'
do until jsonc[idx] = ',' or jsonc[idx] = ']' or jsonc[idx] = '}' or _check_spc(jsonc[idx]) or idx > jsonlen
i ++
lc_value[i] = jsonc[idx]
idx += 1
loop
ls_value = lc_value
idx -= 1
if isnumber(ls_value) then
if pos(ls_value,'E') > 0 or pos(ls_value,'e') > 0 then
la_value = double(ls_value)
elseif pos(ls_value,'.') > 0 then
la_value = dec(ls_value)
else
la_value = long(ls_value)
end if
else
choose case ls_value
case 'true'
la_value = true
case 'false'
la_value = false
case 'null'
setnull(la_value)
case else
return -1
end choose
end if
case else
return -1
end choose
value = la_value
return 0
end function
private subroutine _regenerate_items_idx ();int i
items_idx = '|'
for i = 1 to upperbound(item_list)
items_idx += item_list[i].name + ':' + string(i) + '|'
next
end subroutine
public function integer setitem (string item_name, any item_value);st_item lst_item
int li_idx
any la_item_value
_trans_value(item_value)
li_idx = _get_idx(item_name)
if li_idx < 0 then
lst_item.name = item_name
lst_item.value = item_value
li_idx = upperbound(item_list)+1
item_list[li_idx] = lst_item
items_idx += item_name+':'+string(li_idx)+'|'
else
item_list[li_idx].value = item_value
end if
return li_idx
end function
public function long exportdatarow (any data);long ll_row
int i
string ls_colname,ls_coltype
string ls_item_name
any la_item_value
string ls_cls
string ls_value,ls_date,ls_time,ls_datetime
if upperbound(data) >= 0 then return -1
choose case data.dynamic typeof()
case DataWindow!,DataStore!
case else
return -1
end choose
ll_row = data.dynamic insertrow(0)
for i = 1 to upperbound(item_list)
ls_item_name = item_list[i].name
la_item_value = item_list[i].value
if upperbound(la_item_value) >= 0 then continue
ls_colname = data.dynamic describe(ls_item_name+".name")
if ls_colname = '!' or ls_colname = '?' or ls_colname = '' or isnull(ls_colname) then continue
ls_coltype = data.dynamic describe(ls_item_name+".coltype")
ls_cls = classname(la_item_value)
choose case lower(mid(ls_coltype,1,4))
case 'char' //-->string
if not (ls_cls = 'string') then continue
case 'deci'/*decimal*/,'numb'/*number*/,'long','ulon'/*ulong*/,'real'
if not (ls_cls = 'decimal' or &
ls_cls = 'double' or &
ls_cls = 'integer' or &
ls_cls = 'long' or &
ls_cls = 'unsignedinteger' or &
ls_cls = 'unsignedlong' or &
ls_cls = 'real') then continue
case 'date','time' // date datetime time
if not (ls_cls = 'string') then continue
ls_value = la_item_value
if ls_coltype = 'date' then
la_item_value = _to_date(ls_value)
elseif ls_coltype = 'datetime' then
la_item_value = _to_datetime(ls_value)
elseif ls_coltype = 'time' then
la_item_value = _to_time(ls_value)
end if
case else
continue
end choose
data.dynamic setitem(ll_row,ls_item_name,la_item_value)
next
return ll_row
end function
public function long exportdata (string item_name, any data);any la_list[]
any la_value
long ll_count,i
n_json ljson
long ll_export
la_value = getitem(item_name)
ll_count = upperbound(la_value)
if ll_count < 0 then
la_list[1] = la_value
ll_count = 1
else
la_list = la_value
end if
data.dynamic setredraw(false)
for i = 1 to ll_count
yield()
if not classname(la_list[i]) = classname(this) then continue
ljson = la_list[i]
ljson.exportdatarow(data)
ll_export += 1
next
data.dynamic setredraw(true)
return ll_export
end function
private function integer _parse_json (n_json ajson);string ls_item_name
any la_value,la_list[]
char lc_name[],lc_empty[]
long i
_skip()
do while idx < jsonlen
if jsonc[idx] = '}' then return 0
if jsonc[idx] <> '"' then return -1
ls_item_name = ''
idx += 1
i = 0
lc_name = lc_empty
do until jsonc[idx] = '"'
i ++
lc_name[i] = jsonc[idx]
idx += 1
loop
ls_item_name = lc_name
_skip()
if jsonc[idx] <> ':' then return -1
_skip()
if _parse_value(la_value) < 0 then return -1
ajson.setitem(ls_item_name,la_value)
_skip()
if jsonc[idx] = ',' then
_skip()
elseif jsonc[idx] = '}' then
return 0
end if
loop
return 0
end function
private function date _to_date (string s);date ld
string ls_year,ls_month,ls_day
setnull(ld)
if len(s) <> len(date_format) then return ld
ls_year = mid(s,pos(date_format,'yyyy'),4)
ls_month = mid(s,pos(date_format,'mm'),2)
ls_day = mid(s,pos(date_format,'dd'),2)
if not (isnumber(ls_year) and isnumber(ls_month) and isnumber(ls_day)) then return ld
ld = date(integer(ls_year),integer(ls_month),integer(ls_day))
if string(ld,date_format) <> s then setnull(ld)
return ld
end function
private function time _to_time (string s);time lt
string ls_hour,ls_minute,ls_second
setnull(lt)
if len(s) <> len(time_format) then return lt
ls_hour = mid(s,pos(time_format,'hh'),2)
ls_minute = mid(s,pos(time_format,'mm'),2)
ls_second = mid(s,pos(time_format,'ss'),2)
if not (isnumber(ls_hour) and isnumber(ls_minute) and isnumber(ls_second)) then return lt
lt = time(integer(ls_hour),integer(ls_minute),integer(ls_second))
if string(lt,time_format) <> s then setnull(lt)
return lt
end function
private function datetime _to_datetime (string s);datetime ldt
date ld
time lt
string ls_year,ls_month,ls_day
string ls_hour,ls_minute,ls_second
setnull(ldt)
if len(s) <> len(datetime_format) then return ldt
ls_year = mid(s,pos(date_format,'yyyy'),4)
ls_month = mid(s,pos(date_format,'mm'),2)
ls_day = mid(s,pos(date_format,'dd'),2)
ls_hour = mid(s,pos(time_format,'hh'),2)
ls_minute = mid(s,lastpos(time_format,'mm'),2)
ls_second = mid(s,pos(time_format,'ss'),2)
if not (isnumber(ls_year) and isnumber(ls_month) and isnumber(ls_day) and isnumber(ls_hour) and isnumber(ls_minute) and isnumber(ls_second)) then return ldt
ld = date(integer(ls_year),integer(ls_month),integer(ls_day))
lt = time(integer(ls_hour),integer(ls_minute),integer(ls_second))
ldt = datetime(ld,lt)
if string(ldt,datetime_format) <> s then setnull(ldt)
return ldt
end function
public function long getlistjson (string item_name, ref n_json rjson[]);any la_value,la_list[]
n_json ljson[]
long i
la_value = getitem(item_name)
if upperbound(la_value) < 0 then return -1
la_list = la_value
for i = 1 to upperbound(la_list)
if upperbound(la_list[i]) >= 0 then return -1
if isnull(la_list[i]) then return -1
if classname(la_list[i]) <> classname(this) then return -1
next
rjson = la_list
return upperbound(rjson)
end function
public function any getitempath (string item_path);any la,la_value,la_list_get[],la_list_set[]
n_json ljson_value
long i,ll_len
char lc[]
string ls_item_expression,ls_next_path
lc =item_path
ll_len = upperbound(lc)
if ll_len <= 0 then return la
i = 1
if lc[i] <> '/' then return la
i += 1
do until lc[i] = '/'
ls_item_expression = ls_item_expression + lc[i]
i += 1
if i > ll_len then exit
loop
la_value = getitemexp(ls_item_expression)
if i > ll_len then return la_value
ls_next_path = mid(item_path,i)
if upperbound(la_value) >= 0 then
la_list_get = la_value
for i = 1 to upperbound(la_list_get)
if classname(la_list_get[i]) = classname(this) then
ljson_value = la_list_get[i]
la_list_set[i] = ljson_value.getitempath(ls_next_path)
else
la_list_set[i] = la
end if
next
return la_list_set
else
if classname(la_value) = classname(this) then
ljson_value = la_value
return ljson_value.getitempath(ls_next_path)
else
return la
end if
end if
return la
end function
private function integer _parse_expression (string expression, ref st_name_exp rst_name_exp);char lc[]
string ls_item_name,ls_idx_begin,ls_idx_end
long ll_idx_begin,ll_idx_end
long i = 1
if not match(expression,'.+\[.+\]$') then return -1
lc = expression
do until lc[i] = '['
ls_item_name = ls_item_name + lc[i]
i += 1
loop
i += 1
do until lc[i] = ':' or lc[i] = ']'
ls_idx_begin = ls_idx_begin + lc[i]
i += 1
loop
if ls_idx_begin = '' then ls_idx_begin = '1'
if not isnumber(ls_idx_begin) then return -1
ll_idx_begin = long(ls_idx_begin)
if lc[i] = ':' then
i += 1
do until lc[i] = ']'
ls_idx_end = ls_idx_end + lc[i]
i += 1
loop
if ls_idx_end = '' then ls_idx_end = '0'
if not isnumber(ls_idx_end) then return -1
ll_idx_end = long(ls_idx_end)
if ll_idx_end > 0 and ll_idx_end < ll_idx_begin then return -1
rst_name_exp.islist = true
else
ll_idx_end = ll_idx_begin
rst_name_exp.islist = false
end if
rst_name_exp.name = ls_item_name
rst_name_exp.idx_begin = ll_idx_begin
rst_name_exp.idx_end = ll_idx_end
return 0
end function
public function any getitemexp (string item_expression);any la_value,la_item_value
any la_list_get[],la_list_set[]
long i
st_name_exp lst_name_exp
setnull(la_item_value)
if _parse_expression(item_expression,lst_name_exp) < 0 then return getitem(item_expression)
la_value = getitem(lst_name_exp.name)
if isnull(la_value) then return la_item_value
if upperbound(la_value) < max(lst_name_exp.idx_begin,lst_name_exp.idx_end) then return la_item_value
la_list_get = la_value
if lst_name_exp.isList then
if lst_name_exp.idx_end = 0 then lst_name_exp.idx_end = upperbound(la_list_get)
for i = 1 to lst_name_exp.idx_end - lst_name_exp.idx_begin + 1
la_list_set[i] = la_list_get[lst_name_exp.idx_begin + i - 1]
next
la_item_value = la_list_set
else
la_item_value = la_list_get[lst_name_exp.idx_begin]
end if
return la_item_value
end function
public function integer rename (string item_name, string new_name);int li_idx
li_idx = _get_idx(item_name)
if li_idx < 0 then return -1
item_list[li_idx].name = new_name
_regenerate_items_idx()
return li_idx
end function
private function integer _trans_list (ref any value[]);long i
for i = 1 to upperbound(value)
_trans_value(value[i])
next
return 0
end function
private function integer _trans_value (ref any value);any la_value
if upperbound(value) >= 0 then
_trans_list(value)
return 0
end if
if isnull(value) then return 0
choose case classname(value)
case classname(this)
la_value = value
case 'string'
la_value = value
case 'integer','unsignedinteger','long','unsignedlong','decimal','double','real'
la_value = value
case 'boolean'
la_value = value
case 'date'
la_value = string(value,date_format)
case 'time'
la_value = string(value,time_format)
case 'datetime'
la_value = string(value,datetime_format)
case else
setnull(la_value)
end choose
value = la_value
return 0
end function
public function integer parse (string s);reset()
jsonstr = s
jsonc = s
jsonlen = upperbound(jsonc)
_skip()
if jsonc[idx] <> '{' then return -1
if _parse_json(this) < 0 then return -1
return 0
end function
private function boolean _check_spc (character c);
if c=' ' or c='~r' or c='~n' or c='~t' or c='~b' or c='~f' then return true
return false
end function
public function long getkeys (ref string keys[]);long i
string ls_keys[]
for i = 1 to upperbound(item_list)
ls_keys[i] = item_list[i].name
next
keys = ls_keys
return upperbound(keys)
end function
public function integer _get_data_col (any data, ref st_data_col data_col[]);
int li_colcount
long i,j,p1,p2
string ls_tag,ls_attr_name
any la_value
if upperbound(data) >= 0 then return -1
choose case data.dynamic typeof()
case DataWindow!,DataStore!
case else
return -1
end choose
li_colcount = integer(data.dynamic describe("datawindow.column.count"))
for i = 1 to li_colcount
ls_tag = data.dynamic describe("#"+string(i)+".tag")
p1 = pos(ls_tag,'@attr(')
if p1 > 0 then
p1 += 6
p2 = pos(ls_tag,')',p1)
ls_attr_name = mid(ls_tag,p1,p2 - p1)
if ls_attr_name = 'null' then continue
else
ls_attr_name = ''
end if
j += 1
data_col[j].colname = data.dynamic describe("#"+string(i)+".name")
data_col[j].coltype = data.dynamic describe("#"+string(i)+'.coltype')
if isnull(ls_attr_name) or ls_attr_name='' then ls_attr_name = data_col[j].colname
data_col[j].attrname = ls_attr_name
next
return 0
end function
private function integer _trans_data_row (any data, long row, st_data_col data_col[], ref st_item rst_item[]);
long i,ll_rowcount
any la_value
ll_rowcount = data.dynamic rowcount()
if row > ll_rowcount then return -1
for i = 1 to upperbound(data_col)
choose case lower(left(data_col[i].coltype,4))
case 'char' //string
la_value = data.dynamic getitemstring(row,data_col[i].colname)
if isnull(la_value) then la_value = ''
case 'deci'/*decimal*/
la_value = data.dynamic getitemdecimal(row,data_col[i].colname)
case 'numb'/*number*/,'long','ulon'/*ulong*/,'real'
la_value = data.dynamic getitemnumber(row,data_col[i].colname)
case 'date'
if data_col[i].coltype = 'date' then
la_value = string(data.dynamic getitemdate(row,data_col[i].colname),date_format)
else //datetime
la_value = string(data.dynamic getitemdatetime(row,data_col[i].colname),datetime_format)
end if
if isnull(la_value) then la_value = ''
case 'time'
la_value = string(data.dynamic getitemtime(row,data_col[i].colname),time_format)
if isnull(la_value) then la_value = ''
case else
setnull(la_value)
end choose
rst_item[i].name = data_col[i].attrname
rst_item[i].value = la_value
next
return upperbound(rst_item)
end function
public function integer extend (n_json ajson);
st_item extend_list[]
int li_idx
int i
extend_list = ajson.item_list
for i = 1 to upperbound(extend_list)
li_idx = _get_idx(extend_list[i].name)
if li_idx < 0 then
li_idx = upperbound(item_list)+1
item_list[li_idx] = extend_list[i]
items_idx += extend_list[i].name+':'+string(li_idx)+'|'
else
item_list[li_idx].value = extend_list[i].value
end if
next
return 0
end function
public function string stringify ();char lc_empty[]
idx = 0
jsonc = lc_empty
_stringify_json(this,1)
return jsonc
end function
public subroutine _stringify_json (n_json ajson, integer level);int i
string ls_tab
ajson._fill_jsonc('{')
if pretty_stringify then ls_tab = fill('~t',level - 1)
for i = 1 to upperbound(item_list)
if pretty_stringify then
ajson._fill_jsonc('~r~n~t')
ajson._fill_jsonc(ls_tab)
end if
ajson._fill_jsonc('"')
ajson._fill_jsonc(_trans_name(item_list[i].name))
ajson._fill_jsonc('":')
_stringify_value(ajson,item_list[i].value,level)
if i < upperbound(item_list) then
ajson._fill_jsonc(',')
end if
next
if pretty_stringify then
ajson._fill_jsonc('~r~n')
ajson._fill_jsonc(ls_tab)
end if
ajson._fill_jsonc('}')
return
end subroutine
public subroutine _stringify_list (n_json ajson, any value[], integer level);long i
ajson._fill_jsonc('[')
for i = 1 to upperbound(value)
_stringify_value(ajson,value[i],level)
if i < upperbound(value) then
ajson._fill_jsonc(',')
end if
next
ajson._fill_jsonc(']')
return
end subroutine
public subroutine _stringify_value (n_json ajson, any value, integer level);string ls_value
n_json ljson
char lc_tmp[]
long i
if upperbound(value) >= 0 then
_stringify_list(ajson,value,level)
elseif classname(value) = classname(this) then
ljson = value
ljson.item_name_style = item_name_style
ljson.pretty_stringify = pretty_stringify
ljson._stringify_json(ajson,level + 1)
else
if isnull(classname(value)) then
ajson._fill_jsonc('null')
else
choose case classname(value)
case 'string'
ajson._fill_jsonc('"')
lc_tmp = string(value)
for i = 1 to upperbound(lc_tmp)
choose case lc_tmp[i]
case '\'
ajson._fill_jsonc('\')
if lc_tmp[i + 1] = 'u' then continue
ajson._fill_jsonc('\')
case '"'
ajson._fill_jsonc('\' + lc_tmp[i])
case '~r'
ajson._fill_jsonc('\r')
case '~n'
ajson._fill_jsonc('\n')
case '~t'
ajson._fill_jsonc('\t')
case '~f'
ajson._fill_jsonc('\f')
case '~b'
ajson._fill_jsonc('\b')
case else
ajson._fill_jsonc(lc_tmp[i])
end choose
next
ajson._fill_jsonc('"')
case else
ajson._fill_jsonc(string(value))
end choose
end if
end if
return
end subroutine
public subroutine _fill_jsonc (string s);char lc[]
long i
lc = s
for i = 1 to upperbound(lc)
idx ++
jsonc[idx] = lc[i]
next
end subroutine
public function integer setsql (string item_name, string sql);datastore lds_data
if _sql_to_ds(sql,lds_data) < 0 then return -1
return setdata(item_name,lds_data)
end function
public function integer setsqlrow (string sql, long row);datastore lds_data
if _sql_to_ds(sql,lds_data) < row then return -1
return setdatarow(lds_data,row)
end function
public function boolean hasitem (string item_name);return _get_idx(item_name) > 0
end function
public function integer setsqlrow (string item_name, string sql, long row);datastore lds_data
if _sql_to_ds(sql,lds_data) < row then return -1
return setdatarow(item_name,lds_data,row)
end function
public function integer setsqlrow (string item_name, string sql, long begin_row, long end_row);datastore lds_data
if _sql_to_ds(sql,lds_data) < end_row then return -1
return setdatarow(item_name,lds_data,begin_row,end_row)
end function
public function long _sql_to_ds (string sql, ref datastore ds);string ls_syntax
string ls_err
ls_syntax = SQLCA.SyntaxFromSQL(sql,'Style(Type=Grid)',ls_err)
if len(ls_err) > 0 then return -1
ds = create datastore
ds.create(ls_syntax,ls_err)
if len(ls_err) > 0 then return -1
ds.settransobject(SQLCA)
ds.retrieve()
return ds.rowcount()
end function
on n_json.create
call super::create
TriggerEvent( this, "constructor" )
end on
on n_json.destroy
TriggerEvent( this, "destructor" )
call super::destroy
end on
PB8、PB9版本
更新日志:
功能改进:
数据窗内容输入JSON,数据窗口列属性为隐藏时则不输入,修改_get_data_col。
JSON内容输入数据窗口,字符串类型可以自动转换为数字类型,修改exportdatarow,增加_to_number。
bug修复:
最后一个字符等于\时数组越界,修改_stringify_value。
防止汉字GBK编码后半部分包含\等特殊符号,修改_stringify_value、_parse_value。
mxl 20200329
$PBExportHeader$n_json.sru
forward
global type n_json from nonvisualobject
end type
type st_item from structure within n_json
end type
type st_name_exp from structure within n_json
end type
type st_data_col from structure within n_json
end type
end forward
type st_item from structure
string name
any value
end type
type st_name_exp from structure
string name
boolean islist
long idx_begin
long idx_end
end type
type st_data_col from structure
string colname
string coltype
string attrname
end type
global type n_json from nonvisualobject
event readme ( )
end type
global n_json n_json
type variables
private:
string items_idx='|' // |item1:1|item2:2|
st_item item_list[]
string jsonstr
char jsonc[]
long idx,jsonlen
public:
string date_format = 'yyyy-mm-dd'
string time_format = 'hh:mm:ss'
string datetime_format = 'yyyy-mm-dd hh:mm:ss'
string item_name_style = '' // STYLE_LOWER STYLE_UPPER STYLE_CAMEL STYLE_PASCAL
boolean pretty_stringify
constant string STYLE_LOWER = 'STYLE_LOWER'
constant string STYLE_UPPER = 'STYLE_UPPER'
constant string STYLE_CAMEL = 'STYLE_CAMEL'
constant string STYLE_PASCAL = 'STYLE_PASCAL'
end variables
forward prototypes
public subroutine reset ()
public function any getitem (string item_name)
public function integer delitem (string item_name)
public function integer setdata (string item_name, any data)
public function integer setdatarow (any data, long row)
public function integer setdatarow (string item_name, any data, long row)
private function integer _get_idx (string item_name)
private function string _trans_name (string item_name)
public function integer setdatarow (string item_name, any data, long begin_row, long end_row)
private subroutine _skip ()
private function integer _parse_list (ref any value[])
private function integer _parse_value (ref any value)
private subroutine _regenerate_items_idx ()
public function integer setitem (string item_name, any item_value)
public function long exportdatarow (any data)
public function long exportdata (string item_name, any data)
private function integer _parse_json (n_json ajson)
private function date _to_date (string s)
private function time _to_time (string s)
private function datetime _to_datetime (string s)
public function long getlistjson (string item_name, ref n_json rjson[])
public function any getitempath (string item_path)
private function integer _parse_expression (string expression, ref st_name_exp rst_name_exp)
public function any getitemexp (string item_expression)
public function integer rename (string item_name, string new_name)
private function integer _trans_list (ref any value[])
private function integer _trans_value (ref any value)
public function integer parse (string s)
private function boolean _check_spc (character c)
public function long getkeys (ref string keys[])
public function integer _get_data_col (any data, ref st_data_col data_col[])
private function integer _trans_data_row (any data, long row, st_data_col data_col[], ref st_item rst_item[])
public function integer extend (n_json ajson)
public function string stringify ()
public subroutine _stringify_json (n_json ajson, integer level)
public subroutine _stringify_list (n_json ajson, any value[], integer level)
public subroutine _stringify_value (n_json ajson, any value, integer level)
public subroutine _fill_jsonc (string s)
public function integer setsql (string item_name, string sql)
public function integer setsqlrow (string sql, long row)
public function boolean hasitem (string item_name)
public function integer setsqlrow (string item_name, string sql, long row)
public function integer setsqlrow (string item_name, string sql, long begin_row, long end_row)
public function long _sql_to_ds (string sql, ref datastore ds)
private function decimal _to_number (string s)
end prototypes
public subroutine reset ();st_item lst_items[]
char lc[]
item_list = lst_items
items_idx = '|'
jsonstr = ''
jsonc = lc
idx = 0
jsonlen = 0
end subroutine
public function any getitem (string item_name);any la_item_value
int i
setnull(la_item_value)
i = _get_idx(item_name)
if i > 0 then la_item_value = item_list[i].value
return la_item_value
end function
public function integer delitem (string item_name);int li_idx,i
st_item lst_items[]
li_idx = _get_idx(item_name)
if li_idx < 1 then return -1
for i = 1 to li_idx - 1
lst_items[i] = item_list[i]
next
for i = li_idx + 1 to upperbound(item_list)
lst_items[i - 1] = item_list[i]
next
item_list = lst_items
_regenerate_items_idx()
return 0
end function
public function integer setdata (string item_name, any data);return setdatarow(item_name,data,1,data.dynamic rowcount())
end function
public function integer setdatarow (any data, long row);long i
st_data_col lst_col[]
st_item lst_item[]
if _get_data_col(data,lst_col) < 0 then return -1
if _trans_data_row(data,row,lst_col,lst_item) < 0 then return -1
for i = 1 to upperbound(lst_item)
item_list[upperbound(item_list) + 1] = lst_item[i]
next
_regenerate_items_idx()
return 0
end function
public function integer setdatarow (string item_name, any data, long row);n_json ljson
ljson = create n_json
ljson.date_format = date_format
ljson.time_format = time_format
ljson.datetime_format = datetime_format
ljson.item_name_style = item_name_style
ljson.pretty_stringify = pretty_stringify
ljson.setdatarow(data,row)
return setitem(item_name,ljson)
end function
private function integer _get_idx (string item_name);long ll_pos1,ll_pos2
ll_pos1 = pos(items_idx,'|'+item_name+':')
if ll_pos1 < 1 then return -1
ll_pos1 += len(item_name) + 2
ll_pos2 = pos(items_idx,'|',ll_pos1+1)
return integer(mid(items_idx, ll_pos1, ll_pos2 - ll_pos1))
end function
private function string _trans_name (string item_name);string ls_name
char lc[],lc_name[]
long i,j
boolean lb_trans_flag
//命名规则转换
choose case item_name_style //user_name
case STYLE_UPPER //USER_NAME
ls_name = upper(item_name)
case STYLE_LOWER //user_name
ls_name = lower(item_name)
case STYLE_CAMEL //userName
lc = item_name
for i = 1 to upperbound(lc)
if lc[i] = '_' then
lb_trans_flag = true
continue
end if
j ++
if lb_trans_flag then
lc_name[j] = upper(string(lc[i]))
lb_trans_flag = false
else
lc_name[j] = lower(string(lc[i]))
end if
next
ls_name = lc_name
case STYLE_PASCAL //UserName
lc = item_name
lb_trans_flag = true
for i = 1 to upperbound(lc)
if lc[i] = '_' then
lb_trans_flag = true
continue
end if
j ++
if lb_trans_flag then
lc_name[j] = upper(string(lc[i]))
lb_trans_flag = false
else
lc_name[j] = lower(string(lc[i]))
end if
next
ls_name = lc_name
case else
return item_name
end choose
return ls_name
end function
public function integer setdatarow (string item_name, any data, long begin_row, long end_row);long i,j
n_json ljson_list[]
st_data_col lst_col[]
st_item lst_item[],lst_null[]
if _get_data_col(data,lst_col) < 0 then return -1
for i = begin_row to end_row
lst_item = lst_null
if _trans_data_row(data,i,lst_col,lst_item) < 0 then return -1
j += 1
ljson_list[j] = create n_json
ljson_list[j].date_format = date_format
ljson_list[j].time_format = time_format
ljson_list[j].datetime_format = datetime_format
ljson_list[j].item_name_style = item_name_style
ljson_list[j].pretty_stringify = pretty_stringify
ljson_list[j].item_list = lst_item
ljson_list[j]._regenerate_items_idx()
next
return setitem(item_name,ljson_list)
end function
private subroutine _skip ();char c
do
idx += 1
c = jsonc[idx]
loop while _check_spc(c)
end subroutine
private function integer _parse_list (ref any value[]);long i
any la_list[],la_value_list[]
_skip()
do until jsonc[idx] = ']'
i += 1
if _parse_value(la_list[i]) < 0 then return -1
_skip()
if jsonc[idx] = ',' then _skip()
loop
value = la_list
return 0
end function
private function integer _parse_value (ref any value);string ls_value
n_json ljson
any la_value,la_list[]
long ll_pos
long i
char lc_value[]
choose case jsonc[idx]
case '{'
ljson = create n_json
if _parse_json(ljson) < 0 then return -1
la_value = ljson
case '['
if _parse_list(la_list) < 0 then return -1
la_value = la_list
case '"'
idx += 1
do until jsonc[idx] = '"' or idx > jsonlen
if asc(jsonc[idx]) > 127 then
//防止汉字GBK编码后半部分包含\等特殊符号 MXL 20200326
i ++
lc_value[i] = jsonc[idx]
i ++
lc_value[i] = jsonc[idx + 1]
idx += 2
continue
end if
if jsonc[idx] = '\' then
idx += 1
if not (jsonc[idx] = '"' or jsonc[idx] = '\') then
i ++
choose case jsonc[idx]
case 't'
lc_value[i] = '~t'
case 'r'
lc_value[i] = '~r'
case 'n'
lc_value[i] = '~n'
case 'f'
lc_value[i] = '~f'
case 'b'
lc_value[i] = '~b'
case 'u'
lc_value[i] = '\'
i ++
lc_value[i] = jsonc[idx]
case else
return -1
end choose
idx += 1
continue
end if
end if
i ++
lc_value[i] = jsonc[idx]
idx += 1
loop
ls_value = lc_value
la_value = ls_value
case '0' to '9','+','-',&
't','f',&
'n'
do until jsonc[idx] = ',' or jsonc[idx] = ']' or jsonc[idx] = '}' or _check_spc(jsonc[idx]) or idx > jsonlen
i ++
lc_value[i] = jsonc[idx]
idx += 1
loop
ls_value = lc_value
idx -= 1
if isnumber(ls_value) then
if pos(ls_value,'E') > 0 or pos(ls_value,'e') > 0 then
la_value = double(ls_value)
elseif pos(ls_value,'.') > 0 then
la_value = dec(ls_value)
else
la_value = long(ls_value)
end if
else
choose case ls_value
case 'true'
la_value = true
case 'false'
la_value = false
case 'null'
setnull(la_value)
case else
return -1
end choose
end if
case else
return -1
end choose
value = la_value
return 0
end function
private subroutine _regenerate_items_idx ();int i
items_idx = '|'
for i = 1 to upperbound(item_list)
items_idx += item_list[i].name + ':' + string(i) + '|'
next
end subroutine
public function integer setitem (string item_name, any item_value);st_item lst_item
int li_idx
any la_item_value
_trans_value(item_value)
li_idx = _get_idx(item_name)
if li_idx < 0 then
lst_item.name = item_name
lst_item.value = item_value
li_idx = upperbound(item_list)+1
item_list[li_idx] = lst_item
items_idx += item_name+':'+string(li_idx)+'|'
else
item_list[li_idx].value = item_value
end if
return li_idx
end function
public function long exportdatarow (any data);long ll_row
int i
string ls_colname,ls_coltype
string ls_item_name
any la_item_value
string ls_cls
string ls_value,ls_date,ls_time,ls_datetime
if upperbound(data) >= 0 then return -1
choose case data.dynamic typeof()
case DataWindow!,DataStore!
case else
return -1
end choose
ll_row = data.dynamic insertrow(0)
for i = 1 to upperbound(item_list)
ls_item_name = item_list[i].name
la_item_value = item_list[i].value
if upperbound(la_item_value) >= 0 then continue
ls_colname = data.dynamic describe(ls_item_name+".name")
if ls_colname = '!' or ls_colname = '?' or ls_colname = '' or isnull(ls_colname) then continue
ls_coltype = data.dynamic describe(ls_item_name+".coltype")
ls_cls = classname(la_item_value)
choose case lower(mid(ls_coltype,1,4))
case 'char' //-->string
if not (ls_cls = 'string') then continue
case 'deci'/*decimal*/,'numb'/*number*/,'long','ulon'/*ulong*/,'real'
if not (ls_cls = 'string' or &
ls_cls = 'decimal' or &
ls_cls = 'double' or &
ls_cls = 'integer' or &
ls_cls = 'long' or &
ls_cls = 'unsignedinteger' or &
ls_cls = 'unsignedlong' or &
ls_cls = 'real') then continue
if ls_cls = 'string' then //自动类型转换 尝试将字符串转换成数字 mxl 20200326
ls_value = la_item_value
la_item_value = _to_number(ls_value)
end if
case 'date','time' // date datetime time
if not (ls_cls = 'string') then continue
ls_value = la_item_value
if ls_coltype = 'date' then
la_item_value = _to_date(ls_value)
elseif ls_coltype = 'datetime' then
la_item_value = _to_datetime(ls_value)
elseif ls_coltype = 'time' then
la_item_value = _to_time(ls_value)
end if
case else
continue
end choose
data.dynamic setitem(ll_row,ls_item_name,la_item_value)
next
return ll_row
end function
public function long exportdata (string item_name, any data);any la_list[]
any la_value
long ll_count,i
n_json ljson
long ll_export
la_value = getitem(item_name)
ll_count = upperbound(la_value)
if ll_count < 0 then
la_list[1] = la_value
ll_count = 1
else
la_list = la_value
end if
data.dynamic setredraw(false)
for i = 1 to ll_count
yield()
if not classname(la_list[i]) = classname(this) then continue
ljson = la_list[i]
ljson.exportdatarow(data)
ll_export += 1
next
data.dynamic setredraw(true)
return ll_export
end function
private function integer _parse_json (n_json ajson);string ls_item_name
any la_value,la_list[]
char lc_name[],lc_empty[]
long i
_skip()
do while idx < jsonlen
if jsonc[idx] = '}' then return 0
if jsonc[idx] <> '"' then return -1
ls_item_name = ''
idx += 1
i = 0
lc_name = lc_empty
do until jsonc[idx] = '"'
i ++
lc_name[i] = jsonc[idx]
idx += 1
loop
ls_item_name = lc_name
_skip()
if jsonc[idx] <> ':' then return -1
_skip()
if _parse_value(la_value) < 0 then return -1
ajson.setitem(ls_item_name,la_value)
_skip()
if jsonc[idx] = ',' then
_skip()
elseif jsonc[idx] = '}' then
return 0
end if
loop
return 0
end function
private function date _to_date (string s);date ld
string ls_year,ls_month,ls_day
setnull(ld)
if len(s) <> len(date_format) then return ld
ls_year = mid(s,pos(date_format,'yyyy'),4)
ls_month = mid(s,pos(date_format,'mm'),2)
ls_day = mid(s,pos(date_format,'dd'),2)
if not (isnumber(ls_year) and isnumber(ls_month) and isnumber(ls_day)) then return ld
ld = date(integer(ls_year),integer(ls_month),integer(ls_day))
if string(ld,date_format) <> s then setnull(ld)
return ld
end function
private function time _to_time (string s);time lt
string ls_hour,ls_minute,ls_second
setnull(lt)
if len(s) <> len(time_format) then return lt
ls_hour = mid(s,pos(time_format,'hh'),2)
ls_minute = mid(s,pos(time_format,'mm'),2)
ls_second = mid(s,pos(time_format,'ss'),2)
if not (isnumber(ls_hour) and isnumber(ls_minute) and isnumber(ls_second)) then return lt
lt = time(integer(ls_hour),integer(ls_minute),integer(ls_second))
if string(lt,time_format) <> s then setnull(lt)
return lt
end function
private function datetime _to_datetime (string s);datetime ldt
date ld
time lt
string ls_year,ls_month,ls_day
string ls_hour,ls_minute,ls_second
setnull(ldt)
if len(s) <> len(datetime_format) then return ldt
ls_year = mid(s,pos(date_format,'yyyy'),4)
ls_month = mid(s,pos(date_format,'mm'),2)
ls_day = mid(s,pos(date_format,'dd'),2)
ls_hour = mid(s,pos(time_format,'hh'),2)
ls_minute = mid(s,lastpos(time_format,'mm'),2)
ls_second = mid(s,pos(time_format,'ss'),2)
if not (isnumber(ls_year) and isnumber(ls_month) and isnumber(ls_day) and isnumber(ls_hour) and isnumber(ls_minute) and isnumber(ls_second)) then return ldt
ld = date(integer(ls_year),integer(ls_month),integer(ls_day))
lt = time(integer(ls_hour),integer(ls_minute),integer(ls_second))
ldt = datetime(ld,lt)
if string(ldt,datetime_format) <> s then setnull(ldt)
return ldt
end function
public function long getlistjson (string item_name, ref n_json rjson[]);any la_value,la_list[]
long i
la_value = getitem(item_name)
if upperbound(la_value) < 0 then return -1
la_list = la_value
for i = 1 to upperbound(la_list)
if upperbound(la_list[i]) >= 0 then return -1
if isnull(la_list[i]) then return -1
if classname(la_list[i]) <> classname(this) then return -1
rjson[i] = la_list[i]
next
//rjson = la_list
return upperbound(rjson[])
end function
public function any getitempath (string item_path);any la,la_value,la_list_get[],la_list_set[]
n_json ljson_value
long i,ll_len
char lc[]
string ls_item_expression,ls_next_path
lc =item_path
ll_len = upperbound(lc)
if ll_len <= 0 then return la
i = 1
if lc[i] <> '/' then return la
i += 1
do until lc[i] = '/'
ls_item_expression = ls_item_expression + lc[i]
i += 1
if i > ll_len then exit
loop
la_value = getitemexp(ls_item_expression)
if i > ll_len then return la_value
ls_next_path = mid(item_path,i)
if upperbound(la_value) >= 0 then
la_list_get = la_value
for i = 1 to upperbound(la_list_get)
if classname(la_list_get[i]) = classname(this) then
ljson_value = la_list_get[i]
la_list_set[i] = ljson_value.getitempath(ls_next_path)
else
la_list_set[i] = la
end if
next
return la_list_set
else
if classname(la_value) = classname(this) then
ljson_value = la_value
return ljson_value.getitempath(ls_next_path)
else
return la
end if
end if
return la
end function
private function integer _parse_expression (string expression, ref st_name_exp rst_name_exp);char lc[]
string ls_item_name,ls_idx_begin,ls_idx_end
long ll_idx_begin,ll_idx_end
long i = 1
if not match(expression,'.+\[.+\]$') then return -1
lc = expression
do until lc[i] = '['
ls_item_name = ls_item_name + lc[i]
i += 1
loop
i += 1
do until lc[i] = ':' or lc[i] = ']'
ls_idx_begin = ls_idx_begin + lc[i]
i += 1
loop
if ls_idx_begin = '' then ls_idx_begin = '1'
if not isnumber(ls_idx_begin) then return -1
ll_idx_begin = long(ls_idx_begin)
if lc[i] = ':' then
i += 1
do until lc[i] = ']'
ls_idx_end = ls_idx_end + lc[i]
i += 1
loop
if ls_idx_end = '' then ls_idx_end = '0'
if not isnumber(ls_idx_end) then return -1
ll_idx_end = long(ls_idx_end)
if ll_idx_end > 0 and ll_idx_end < ll_idx_begin then return -1
rst_name_exp.islist = true
else
ll_idx_end = ll_idx_begin
rst_name_exp.islist = false
end if
rst_name_exp.name = ls_item_name
rst_name_exp.idx_begin = ll_idx_begin
rst_name_exp.idx_end = ll_idx_end
return 0
end function
public function any getitemexp (string item_expression);any la_value,la_item_value
any la_list_get[],la_list_set[]
long i
st_name_exp lst_name_exp
setnull(la_item_value)
if _parse_expression(item_expression,lst_name_exp) < 0 then return getitem(item_expression)
la_value = getitem(lst_name_exp.name)
if isnull(la_value) then return la_item_value
if upperbound(la_value) < max(lst_name_exp.idx_begin,lst_name_exp.idx_end) then return la_item_value
la_list_get = la_value
if lst_name_exp.isList then
if lst_name_exp.idx_end = 0 then lst_name_exp.idx_end = upperbound(la_list_get)
for i = 1 to lst_name_exp.idx_end - lst_name_exp.idx_begin + 1
la_list_set[i] = la_list_get[lst_name_exp.idx_begin + i - 1]
next
la_item_value = la_list_set
else
la_item_value = la_list_get[lst_name_exp.idx_begin]
end if
return la_item_value
end function
public function integer rename (string item_name, string new_name);int li_idx
li_idx = _get_idx(item_name)
if li_idx < 0 then return -1
item_list[li_idx].name = new_name
_regenerate_items_idx()
return li_idx
end function
private function integer _trans_list (ref any value[]);long i
any la_value
for i = 1 to upperbound(value)
la_value = value[i]
_trans_value(la_value)
value[i] = la_value
next
return 0
end function
private function integer _trans_value (ref any value);any la_value
if upperbound(value) >= 0 then
_trans_list(value)
return 0
end if
if isnull(value) then return 0
choose case classname(value)
case classname(this)
la_value = value
case 'string'
la_value = value
case 'integer','unsignedinteger','long','unsignedlong','decimal','double','real'
la_value = value
case 'boolean'
la_value = value
case 'date'
la_value = string(value,date_format)
case 'time'
la_value = string(value,time_format)
case 'datetime'
la_value = string(value,datetime_format)
case else
setnull(la_value)
end choose
value = la_value
return 0
end function
public function integer parse (string s);reset()
jsonstr = s
jsonc = s
jsonlen = upperbound(jsonc)
_skip()
if jsonc[idx] <> '{' then return -1
if _parse_json(this) < 0 then return -1
return 0
end function
private function boolean _check_spc (character c);
if c=' ' or c='~r' or c='~n' or c='~t' or c='~b' or c='~f' then return true
return false
end function
public function long getkeys (ref string keys[]);long i
string ls_keys[]
for i = 1 to upperbound(item_list)
ls_keys[i] = item_list[i].name
next
keys = ls_keys
return upperbound(keys)
end function
public function integer _get_data_col (any data, ref st_data_col data_col[]);
int li_colcount
long i,j,p1,p2
string ls_tag,ls_attr_name
string ls_col_visible //mxl 20200313
any la_value
if upperbound(data) >= 0 then return -1
choose case data.dynamic typeof()
case DataWindow!,DataStore!
case else
return -1
end choose
li_colcount = integer(data.dynamic describe("datawindow.column.count"))
for i = 1 to li_colcount
ls_tag = data.dynamic describe("#"+string(i)+".tag")
p1 = pos(ls_tag,'@attr(')
if p1 > 0 then
p1 += 6
p2 = pos(ls_tag,')',p1)
ls_attr_name = mid(ls_tag,p1,p2 - p1)
if ls_attr_name = 'null' then continue
else
ls_attr_name = ''
end if
ls_col_visible = data.dynamic describe("#"+string(i)+".visible")
if ls_col_visible = '0' then continue //列属性为隐藏则不导出 mxl 20200313
j += 1
data_col[j].colname = data.dynamic describe("#"+string(i)+".name")
data_col[j].coltype = data.dynamic describe("#"+string(i)+'.coltype')
if isnull(ls_attr_name) or ls_attr_name='' then ls_attr_name = data_col[j].colname
data_col[j].attrname = ls_attr_name
next
return 0
end function
private function integer _trans_data_row (any data, long row, st_data_col data_col[], ref st_item rst_item[]);
long i,ll_rowcount
any la_value
ll_rowcount = data.dynamic rowcount()
if row > ll_rowcount then return -1
for i = 1 to upperbound(data_col)
choose case lower(left(data_col[i].coltype,4))
case 'char' //string
la_value = data.dynamic getitemstring(row,data_col[i].colname)
if isnull(la_value) then la_value = ''
case 'deci'/*decimal*/
la_value = data.dynamic getitemdecimal(row,data_col[i].colname)
case 'numb'/*number*/,'long','ulon'/*ulong*/,'real'
la_value = data.dynamic getitemnumber(row,data_col[i].colname)
case 'date'
if data_col[i].coltype = 'date' then
la_value = string(data.dynamic getitemdate(row,data_col[i].colname),date_format)
else //datetime
la_value = string(data.dynamic getitemdatetime(row,data_col[i].colname),datetime_format)
end if
if isnull(la_value) then la_value = ''
case 'time'
la_value = string(data.dynamic getitemtime(row,data_col[i].colname),time_format)
if isnull(la_value) then la_value = ''
case else
setnull(la_value)
end choose
rst_item[i].name = data_col[i].attrname
rst_item[i].value = la_value
next
return upperbound(rst_item)
end function
public function integer extend (n_json ajson);
st_item extend_list[]
int li_idx
int i
extend_list = ajson.item_list
for i = 1 to upperbound(extend_list)
li_idx = _get_idx(extend_list[i].name)
if li_idx < 0 then
li_idx = upperbound(item_list)+1
item_list[li_idx] = extend_list[i]
items_idx += extend_list[i].name+':'+string(li_idx)+'|'
else
item_list[li_idx].value = extend_list[i].value
end if
next
return 0
end function
public function string stringify ();char lc_empty[]
idx = 0
jsonc = lc_empty
_stringify_json(this,1)
return jsonc
end function
public subroutine _stringify_json (n_json ajson, integer level);int i
string ls_tab
ajson._fill_jsonc('{')
if pretty_stringify then ls_tab = fill('~t',level - 1)
for i = 1 to upperbound(item_list)
if pretty_stringify then
ajson._fill_jsonc('~r~n~t')
ajson._fill_jsonc(ls_tab)
end if
ajson._fill_jsonc('"')
ajson._fill_jsonc(_trans_name(item_list[i].name))
ajson._fill_jsonc('":')
_stringify_value(ajson,item_list[i].value,level)
if i < upperbound(item_list) then
ajson._fill_jsonc(',')
end if
next
if pretty_stringify then
ajson._fill_jsonc('~r~n')
ajson._fill_jsonc(ls_tab)
end if
ajson._fill_jsonc('}')
return
end subroutine
public subroutine _stringify_list (n_json ajson, any value[], integer level);long i
ajson._fill_jsonc('[')
for i = 1 to upperbound(value)
_stringify_value(ajson,value[i],level)
if i < upperbound(value) then
ajson._fill_jsonc(',')
end if
next
ajson._fill_jsonc(']')
return
end subroutine
public subroutine _stringify_value (n_json ajson, any value, integer level);string ls_value
n_json ljson
char lc_tmp[]
long i
if upperbound(value) >= 0 then
_stringify_list(ajson,value,level)
elseif classname(value) = classname(this) then
ljson = value
ljson.item_name_style = item_name_style
ljson.pretty_stringify = pretty_stringify
ljson._stringify_json(ajson,level + 1)
else
if isnull(classname(value)) then
ajson._fill_jsonc('null')
else
choose case classname(value)
case 'string'
ajson._fill_jsonc('"')
lc_tmp = string(value)
for i = 1 to upperbound(lc_tmp)
if asc(lc_tmp[i]) > 127 then
//防止汉字GBK编码后半部分包含\等特殊符号 MXL 20200326
ajson._fill_jsonc(lc_tmp[i] + lc_tmp[i + 1])
i ++
continue
end if
choose case lc_tmp[i]
case '\'
ajson._fill_jsonc('\')
if i < upperbound(lc_tmp) then //防止数组越界 MXL 20200326
if lc_tmp[i + 1] = 'u' then continue
end if
ajson._fill_jsonc('\')
case '"'
ajson._fill_jsonc('\' + lc_tmp[i])
case '~r'
ajson._fill_jsonc('\r')
case '~n'
ajson._fill_jsonc('\n')
case '~t'
ajson._fill_jsonc('\t')
case '~f'
ajson._fill_jsonc('\f')
case '~b'
ajson._fill_jsonc('\b')
case else
ajson._fill_jsonc(lc_tmp[i])
end choose
next
ajson._fill_jsonc('"')
case else
ajson._fill_jsonc(string(value))
end choose
end if
end if
return
end subroutine
public subroutine _fill_jsonc (string s);char lc[]
long i
lc = s
for i = 1 to upperbound(lc)
idx ++
jsonc[idx] = lc[i]
next
end subroutine
public function integer setsql (string item_name, string sql);datastore lds_data
if _sql_to_ds(sql,lds_data) < 0 then return -1
return setdata(item_name,lds_data)
end function
public function integer setsqlrow (string sql, long row);datastore lds_data
if _sql_to_ds(sql,lds_data) < row then return -1
return setdatarow(lds_data,row)
end function
public function boolean hasitem (string item_name);return _get_idx(item_name) > 0
end function
public function integer setsqlrow (string item_name, string sql, long row);datastore lds_data
if _sql_to_ds(sql,lds_data) < row then return -1
return setdatarow(item_name,lds_data,row)
end function
public function integer setsqlrow (string item_name, string sql, long begin_row, long end_row);datastore lds_data
if _sql_to_ds(sql,lds_data) < end_row then return -1
return setdatarow(item_name,lds_data,begin_row,end_row)
end function
public function long _sql_to_ds (string sql, ref datastore ds);string ls_syntax
string ls_err
ls_syntax = SQLCA.SyntaxFromSQL(sql,'Style(Type=Grid)',ls_err)
if len(ls_err) > 0 then return -1
ds = create datastore
ds.create(ls_syntax,ls_err)
if len(ls_err) > 0 then return -1
ds.settransobject(SQLCA)
ds.retrieve()
return ds.rowcount()
end function
private function decimal _to_number (string s);//新增功能:将字符串转换成数字 mxl 20200326
dec ldc
setnull(ldc)
if not (isnumber(s)) then return ldc
ldc = dec(s)
return ldc
end function
on n_json.create
call super::create
TriggerEvent( this, "constructor" )
end on
on n_json.destroy
TriggerEvent( this, "destructor" )
call super::destroy
end on