PB结构化存储与解析JSON

PB JSON 数据结构

JSON 语法

JSON语法规则

1.数据表示为 名称/值对
2.数据之间由逗号分隔
3.花括号 { } 保存JSON对象
4.方括号 [ ] 保存数组

{"code" : 1, "name" : "prime", "value" : [2,3,5,7,11,13]}

JSON 值

JSON数据的值可以是:
1.数值

{"item" : 3.14159265358979}

2.字符串

{"item" : "foobar"}

3.布尔值

{"item" : true}

4.null

{"item" : null}

5.数组

{"item" : [17,19,23,29,31,37]}
{"item" : ["foo","bar"]}

6.JSON对象

{"item" : {"subItem" : "foobar"}}

数组

数组的值可以是任何一种数据的值,包括数组本身

[2,3,5,7,11,13]
["foo","bar","baz"]
[true,false,true,false]
[null , {} , {"item" : [ "foo","bar"]} , [17,19,23,29,31,37] ]

PB JSON 数据结构使用

组装JSON

只需要一个方法 setItem

n_json ljson_main,ljson_value,ljson_list[]
any la_value[],la_empty[]
string ls_null
string ls_json

ljson_main = create n_json
ljson_value = create n_json
ljson_list[1] = create n_json
ljson_list[2] = create n_json

ljson_main.setItem("number_1",123) //设置数值
ljson_main.setItem("number_2",3.14) //设置数值

ljson_main.setItem("string_1","foo") //设置字符串
ljson_main.setItem("string_2","bar") //设置字符串
ljson_main.setItem("string_3",today()) //设置日期,自动转为字符串

ljson_main.setItem("boolean_1",false) //设置布尔值

setnull(ls_null)
ljson_main.setItem("null_1",ls_null) //设置null

ljson_value.setItem("value","value1")
ljson_main.setItem("json_1",ljson_value) //设置JSON对象

ljson_main.setItem("array_1",{2,3,5,7,11,13}) //设置数值列表

ljson_list[1].setItem("item","list1")
ljson_list[2].setItem("item","list2")
ljson_main.setItem("array_2",ljson_list) //设置JSON对象列表

la_value[1] = 100
la_value[2] = "200"
ljson_main.setItem("array_3",la_value) //设置混合类型列表

ljson_main.setItem("array_4",la_empty) //设置空列表

ljson_main.pretty_print = true //输出字符串自动换行美化格式
ls_json = ljson_main.getFormat()

destroy ljson_main
destroy ljson_value
destroy ljson_list[1]
destroy ljson_list[2]

return 0

以上代码执行完成后ls_json值为:

{
	"number_1":123,
	"number_2":3.14,
	"string_1":"foo",
	"string_2":"bar",
	"string_3":"2019-03-30",
	"boolean_1":false,
	"null_1":null,
	"json_1":{
		"value":"value1"
	},
	"array_1":[2,3,5,7,11,13],
	"array_2":[{
		"item":"list1"
	},{
		"item":"list2"
	}],
	"array_3":[100,"200"],
	"array_4":[]
}

解析JSON

string ls_json
n_json ljson_main

ls_json = '{' +&
			'"corp":"MacroSoft",' +&
			'"business":["software","computer science","energy"],' +&
			'"employeeCount":3,' +&
			'"employees": [' +&
			'{ "firstName":"John" , "lastName":"Doe" },' +&
			'{ "firstName":"Anna" , "lastName":"Smith" },' +&
			'{ "firstName":"Peter" , "lastName":"Jones" }' +&
			']' +&
			'}'

ljson_main = create n_json
ljson_main.parse(ls_json) //解析JSON字符串

string ls_corp,ls_business[]
integer li_employee_count,i
n_json ljson_employee[]
string ls_firstname,ls_lastname

ls_corp = ljson_main.getItem("corp") //获取 corp 字符串
ls_business = ljson_main.getItem("business") //获取 business 字符串列表
li_employee_count = ljson_main.getItem("employeeCount") //获取 employeeCount 数值
ljson_main.getListJSON("employees",ljson_employee) //获取 employees JSON列表
for i= 1 to upperbound(ljson_employee) //循环遍历 employees 内部数据
	ls_firstname = ljson_employee[i].getitem("firstName")
	ls_lastname = ljson_employee[i].getitem("lastName")
next

destroy ljson_main

return 0

DataWindow与DataStore接口

数据窗内容输入JSON

数据窗1

dw_data.accepttext()

n_json ljson_data1,ljson_data2,ljson_data3,ljson_data4
string ls_data1,ls_data2,ls_data3,ls_data4

ljson_data1 = create n_json
ljson_data2 = create n_json
ljson_data3 = create n_json
ljson_data4 = create n_json

ljson_data1.setData("employees",dw_data) //数据窗全部内容作为列表设置到 employees 的值
ljson_data2.setDataRow("employees",dw_data,1,2) //数据窗第1到2行内容作为列表设置到 employees 的值
ljson_data3.setDataRow("employee",dw_data,3) //数据窗第3行内容作为JSON对象设置到 employee 的值
ljson_data4.setDataRow(dw_data,1) //数据窗第1行各字段数据设置到该JSON对象

ljson_data1.pretty_print = true
ljson_data2.pretty_print = true
ljson_data3.pretty_print = true
ljson_data4.pretty_print = true

ls_data1 = ljson_data1.getFormat()
ls_data2 = ljson_data2.getFormat()
ls_data3 = ljson_data3.getFormat()
ls_data4 = ljson_data4.getFormat()

destroy ljson_data1
destroy ljson_data2
destroy ljson_data3
destroy ljson_data4

return 0

代码执行后,字符串的值如下

// ls_data1的值
{
	"employees":[{
		"first_name":"Thomas",
		"last_name":"Wade",
		"age":45
	},{
		"first_name":"Beihai",
		"last_name":"Zhang",
		"age":36
	},{
		"first_name":"Jason",
		"last_name":"Friday",
		"age":33
	}]
}

// ls_data2的值
{
	"employees":[{
		"first_name":"Thomas",
		"last_name":"Wade",
		"age":45
	},{
		"first_name":"Beihai",
		"last_name":"Zhang",
		"age":36
	}]
}

// ls_data3的值
{
	"employee":{
		"first_name":"Jason",
		"last_name":"Friday",
		"age":33
	}
}

// ls_data4的值
{
	"first_name":"Thomas",
	"last_name":"Wade",
	"age":45
}

数据存储接口调用方式和数据窗完全相同

JSON内容输入数据窗
string ls_data
n_json ljson_data

ls_data = '{' +&
			'	"first_name":"Donald",' +&
			'	"last_name":"Trump",' +&
			'	"age":70' +&
			'}'

ljson_data = create n_json
ljson_data.parse(ls_data)

ljson_data.exportDataRow(dw_data) //JSON内容输出到数据窗最后一行

destroy ljson_data
return 0

执行后结果如下
在这里插入图片描述

string ls_data
n_json ljson_data

ls_data = '{' +&
			'	"presidents":[{' +&
			'		"first_name":"Donald",' +&
			'		"last_name":"Trump",' +&
			'		"age":70' +&
			'	},{' +&
			'		"first_name":"Vladimir",' +&
			'		"last_name":"Putin",' +&
			'		"age":66' +&
			'	}]' +&
			'}' 

ljson_data = create n_json
ljson_data.parse(ls_data)

ljson_data.exportData("presidents",dw_data) //JSON 的 presidents 值输出到数据窗

destroy ljson_data
return 0

执行后结果如下
在这里插入图片描述
数据存储接口调用方式和数据窗完全相同

表达式搜索与路径搜索

表达式支持这些格式:

item[x] //item值列表的第x项
item[x:y] //item值列表的第x至第y项
item[x:] //item值列表第x项开始之后所有值
item[:y] //item值列表自第1项至第y项所有值
item[:] //item值列表
item //item值(可以是列表或非列表)

路径就是斜线 / 后面跟上表达式连接而成
表达式搜索或路径搜索返回的结果必须赋值给对应类型的数据结构,没有该类型数据结构的情况只能先赋值给any类型

string ls_data
n_json ljson_data
dec{8} ldc_pi,ldc_e
long ll_primes[],ll_prime
string ls_name[]

ls_data = '{ "primes" : [2,3,5,7,11,13,17,19,23,29,31,37] ,' +&
			' "transcendentalNumbers" : [ {"name":"pi" , "value":3.14159265} , {"name":"e" , "value":2.71828183} ]   '+&
			'} '  
			

ljson_data = create n_json
ljson_data.parse(ls_data)

// 表达式搜索
ll_primes = ljson_data.getItemExp("primes[:]") // => [2,3,5,7,11,13,17,19,23,29,31,37] 
ll_primes = ljson_data.getItemExp("primes[2:4]") // => [3,5,7]
ll_primes = ljson_data.getItemExp("primes[:6]") // => [2,3,5,7,11,13]
ll_primes = ljson_data.getItemExp("primes[7:]") // => [17,19,23,29,31,37]
ll_prime = ljson_data.getItemExp("primes[7]") // => 17

// 路径搜索
ldc_pi = ljson_data.getItemPath("/transcendentalNumbers[1]/value") // => 3.14159265
ls_name= ljson_data.getItemPath("/transcendentalNumbers/name") // => ["pi","e"]

destroy ljson_data
return 0

其他方法与属性

1.重置数据结构

ljson_data.reset()

2.删除键值对

ljson_data.delItem("foo")

3.键重命名

ljson_data.rename("foo","bar")

4.判断是否包含键

string ls_foo
if ljson_data.contains("foo") then
	ls_foo = ljson_data.getitem("foo")
end if

5.输出字符串键的命名风格
实例变量 public string item_name_style
支持类型:
STYLE_LOWER //小写命名 e.g. user_name
STYLE_UPPER //大写命名 e.g. USER_NAME
STYLE_CAMEL //骆驼命名 e.g. userName
STYLE_PASCAL //帕斯卡命名 e.g. UserName

PB JSON 数据结构源代码

解析字符方法要点

私有方法:
_parse_json
_parse_list
_parse_value
逐字符读取JSON字符串,读取到花括号 { 时调用 _parse_json 解析JSON对象,读取到方括号 [ 时调用 _parse_list 解析列表,读取到冒号 : 时调用 _parse_value 解析值,三个方法内部互相递归,完全解析任意格式JSON字符串。

输出字符方法要点

私有方法:
_get_format_json
_get_format_list
_get_format_value
遍历数据结构每个键值对,需要输出JSON字符串时调用 _get_format_json ,需要输出列表字符串时调用 _get_format_list ,需要输出值字符串时调用 _get_format_value ,三个方法内部互相递归,将任意的JSON实例输出到字符串。

源代码

代码拷贝到文本编辑器,另存为 n_json.sru,导入pbl
新版本:PB JSON工具n_json新版本
发现BUG请留言或私信,以便修正(QQ:768310524 TEL:18649713925)

$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
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

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_print
	
	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 string getformat ()
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 function string _get_format_json (integer level)
private subroutine _skip ()
private function integer _parse_list (ref any value[])
private function integer _parse_value (ref any value)
private subroutine _regenerate_items_idx ()
private function string _get_format_list (any value[], integer level)
private function string _get_format_value (any value, integer level)
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)
private function integer _trans_data_row (any data, long row, ref st_item rst_item[])
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)
public function boolean contains (string item_name)
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 string getformat ();return _get_format_json(1)
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_item lst_item[]

if  _trans_data_row(data,row,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_print = pretty_print
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[]
long i
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
		do while i < len(lc)
			i += 1
			if lc[i] = '_' then 
				lb_trans_flag = true
				continue
			end if
			if lb_trans_flag then
				ls_name += upper(string(lc[i]))
				lb_trans_flag = false
			else
				ls_name += lower(string(lc[i]))
			end if
		loop 
	case STYLE_PASCAL //UserName
		lc = item_name
		lb_trans_flag = true
		do while i < len(lc)
			i += 1
			if lc[i] = '_' then 
				lb_trans_flag = true
				continue
			end if
			if lb_trans_flag then
				ls_name += upper(string(lc[i]))
				lb_trans_flag = false
			else
				ls_name += lower(string(lc[i]))
			end if
		loop 
	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_item lst_item[],lst_null[]

for i = begin_row to end_row
	lst_item = lst_null
	if _trans_data_row(data,i,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_print = pretty_print
	ljson_list[j].item_list = lst_item
	ljson_list[j]._regenerate_items_idx()
next

return setitem(item_name,ljson_list)

end function

private function string _get_format_json (integer level);int i
string ls_tab
string ls_json,ls_name_value

if pretty_print then ls_tab = fill('~t',level - 1)

for i = 1 to upperbound(item_list)
	ls_name_value = ''
	if pretty_print then ls_name_value += '~r~n~t' + ls_tab
	ls_name_value += '"'+_trans_name(item_list[i].name)+'"'+':'
	ls_name_value += _get_format_value(item_list[i].value,level)

	if i < upperbound(item_list) then ls_name_value += ','
	ls_json += ls_name_value
next
if pretty_print then ls_json += '~r~n'+ls_tab

return '{'+ls_json+'}'
end function

private subroutine _skip ();char c

do 
   idx += 1
   c = jsonc[idx]
loop while c=' ' or c='~r' or c='~n' or c='~t' or c='~b' or c='~f'

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

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
					choose case jsonc[idx]
						case 't'
							ls_value += '~t'
						case 'r'
							ls_value += '~r'
						case 'n'
							ls_value += '~n'
						case 'f'
							ls_value += '~f'
						case 'b'
							ls_value += '~b'
						case else
							return -1
					end choose
					idx += 1
					continue
				end if
			end if
			ls_value = ls_value + jsonc[idx]
			idx += 1
		loop
//		do
//			ll_pos = pos(jsonstr,'"',idx)
//			if ll_pos <= 0 then return -1
//			if jsonc[ll_pos - 1] = '\' then
//				ls_value += mid(jsonstr,idx,ll_pos - idx - 1)
//				idx = ll_pos + 1
//			else
//				ls_value += mid(jsonstr,idx,ll_pos - idx)
//				idx = ll_pos
//				exit
//			end if
//		loop until idx >= jsonlen
		la_value = ls_value
	case '0' to '9','+','-',&
		   't','f',&
		   'n'
		do until jsonc[idx] = ',' or jsonc[idx] = ']' or jsonc[idx] = '}' or idx > jsonlen
			ls_value = ls_value + jsonc[idx]
			idx += 1
		loop
		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

private function string _get_format_list (any value[], integer level);long i
string ls_item_list

for i = 1 to upperbound(value)
	ls_item_list += _get_format_value(value[i],level)
	if i < upperbound(value) then ls_item_list += ','
next

return '['+ls_item_list+']'
end function

private function string _get_format_value (any value, integer level);string ls_value
n_json ljson
char lc[]
long i

if upperbound(value) >= 0 then
	ls_value = _get_format_list(value,level)
elseif classname(value) = classname(this) then
	ljson = value
	ljson.item_name_style = item_name_style
	ljson.pretty_print = pretty_print
	ls_value = ljson._get_format_json(level + 1)
else
	if isnull(classname(value)) then
		ls_value = 'null'
	else
		choose case classname(value)
			case 'string'
				lc = string(value)
				for i = 1 to upperbound(lc)
//					if lc[i] = '"' or lc[i] = '\' then ls_value += '\'
//					ls_value = ls_value + lc[i]
					choose case lc[i]
						case '"','\'
							ls_value += '\' + lc[i]
						case '~r'
							ls_value += '\r'
						case '~n'
							ls_value += '\n'
						case '~t'
							ls_value += '\t'
						case '~f'
							ls_value += '\f'
						case '~b'
							ls_value += '\b'
						case else
							ls_value = ls_value + lc[i]
					end choose
				next
				ls_value = '"'+ls_value+'"'
			case else
				ls_value = string(value)
		end choose
	end if
end if

return ls_value

end function

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
else
	la_list = la_value
end if

for i = 1 to ll_count
	if not classname(la_list[i]) = classname(this) then continue
	ljson = la_list[i]
	ljson.exportdatarow(data)
	ll_export += 1
next

return ll_export

end function

private function integer _parse_json (n_json ajson);string ls_item_name
any la_value,la_list[]

_skip()
do while idx < jsonlen
	if jsonc[idx] = '}' then return 0
	if jsonc[idx] <> '"' then return -1
	ls_item_name = ''
	
	idx += 1
	do until jsonc[idx] = '"'
		ls_item_name = ls_item_name + jsonc[idx]
		idx += 1
	loop
	
	_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

private function integer _trans_data_row (any data, long row, ref st_item rst_item[]);int li_colcount
string ls_colname[],ls_coltype[]
long i,j,ll_rowcount
any la_value

if upperbound(data) >= 0 then return -1
choose case data.dynamic typeof()
	case DataWindow!,DataStore!
	case else
		return -1
end choose

ll_rowcount = data.dynamic rowcount()
if row > ll_rowcount then return -1
li_colcount = integer(data.dynamic describe("datawindow.column.count"))
for i = 1 to li_colcount
	if data.dynamic describe("#"+string(i)+".tag") = 'ETH' then continue
	j += 1
	ls_colname[j] = data.dynamic describe("#"+string(i)+".name")
	ls_coltype[j] = data.dynamic describe(ls_colname[j]+'.coltype')
next

for i = 1 to upperbound(ls_colname)
	choose case lower(left(ls_coltype[i],4))
		case 'char'	//string
			la_value = data.dynamic getitemstring(row,ls_colname[i])
			if isnull(la_value) then la_value = ''
		case 'deci'/*decimal*/
			la_value = data.dynamic getitemdecimal(row,ls_colname[i])
		case 'numb'/*number*/,'long','ulon'/*ulong*/,'real'
			la_value = data.dynamic getitemnumber(row,ls_colname[i])
		case 'date'
			if ls_coltype[i] = 'date' then
				la_value = string(data.dynamic getitemdate(row,ls_colname[i]),date_format)
			else //datetime
				la_value = string(data.dynamic getitemdatetime(row,ls_colname[i]),datetime_format)
			end if
			if isnull(la_value) then la_value = ''
		case 'time'
			la_value = string(data.dynamic getitemtime(row,ls_colname[i]),time_format)
			if isnull(la_value) then la_value = ''
		case else
			setnull(la_value)
	end choose
	rst_item[i].name = ls_colname[i]
	rst_item[i].value = la_value
next

return upperbound(rst_item)
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

public function boolean contains (string item_name);if _get_idx(item_name) < 0 then 
	return false
else
	return true
end if
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

备注

某些PB版本调用getlistjson方法报错 error:type mismatch in array to object conversion,需要修改getlistjson方法:

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[])

在PB WebService服务端运行时,私有方法_trans_list可能会报错,解决方式代码修改如下:

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
  • 29
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值