封面图像版权所有Sergio Mijatovic 2022
以不同的方式解析JSON
此示例演示了用Vely在C中解析JSON文本。文本解析包含有关城市的信息。 JSON文件包括一系列国家,其中包括一系列国家,每个国家都有一系列城市。 JSON数据也不是固定的 - 一些数组成员包含的数据不包含其他数组。因此,示例相当涉及。
还显示了UTF8 Unicode数据的使用 - 一些城市的名称中具有此类字符。
JSON文本来自两种不同类型的客户端请求:来自HTML表单,也来自JavaScript/fetch()。第一个使用表格中使用URL Query帖子。第二个演示了使用``application/json content类型''的请求,并使用request-body获取HTTP请求正文。
使用内置哈希语句检索每个JSON数据节点(请参见new-json)。
JSON解析演示了两种方法:
-
首先,通过搜索特定要素,在这种情况下,所有国家,然后是一个国家下的所有州,然后是国家下的所有城市。这说明了如何处理已知结构但可以更改的通用JSON文档。
-
第二,通过遍历所有数据节点并将每个数据节点循环中。这对于获取所有数据也很有用,即使您不知道其结构并在此过程中寻找您感兴趣的内容。
应用程序的屏幕截图
这是您可以输入JSON文本进行解析的形式:
这是使用“提取所有数据”按钮提交的结果,其中显示了所有数据节点以及它们的归一化名称(包括层次结构和数组),它们的值和类型:
以下是按下提取特定数据按钮的输出。考虑到数据的层次结构及其名称和值显示:
,找到了特定的数据节点。您可以从javascript fetch()调用vely代码 - 这是post.html的输出(请参阅“访问应用程序”如何运行它):
设置先决条件
Install Vely您可以使用标准包装工具,例如apt,dnf,pacman或zypper。
因为它在此示例中使用,因此您需要安装Nginx作为Web服务器。
安装Vely后,如果您使用它,请在VIM中打开语法突出显示:
vv -m
获取源代码
源代码是Vely安装的一部分。为每个应用程序创建一个单独的源代码目录是一个好主意(您可以随心所欲地将其命名)。在这种情况下,解开源代码将为您做到这一点:
tar xvf $(vv -o)/examples/json.tar.gz
cd json
设置应用程序
第一步是创建一个应用程序。该应用程序将被命名为JSON,但是您可以将其命名(如果这样做,请在任何地方更改)。与vf一起工作很简单:
sudo vf -i -u $(whoami) json
这将创建一个新的应用程序主页(即/var/lib/vv/json),并为您进行应用程序设置。通常,这意味着在主文件夹中创建各种子目录,并为其分配特权。在这种情况下,只有当前用户(或Whoami Linux命令的结果)将拥有具有0700特权的目录;这意味着安全设置。
构建应用程序
使用vv实用程序来制作应用程序:
vv -q
启动您的应用程序服务器
启动用于Web应用程序的应用程序服务器使用vf FastCGI Process Manager。应用程序服务器将使用UNIX套接字与Web服务器进行通信(即反向Proxy):
vf -w 3 json
这将启动3个守护程序进程,以服务传入的请求。您还可以启动一台自适应服务器,该服务器将增加提供更多请求的过程的数量,并在不需要的过程中逐渐减少这些过程的数量:
vf json
有关更多选项,请参见vf,以帮助您实现最佳性能。
停止您的应用程序服务器:
vf -m quit json
设置Web服务器
这显示了如何连接您在UNIX插座(以vf开头)上侦听的应用程序到Nginx Web服务器。
步骤1 :
您需要编辑Nginx配置文件。对于Ubuntu和类似:
sudo vi /etc/nginx/sites-enabled/default
在Fedora和其他系统上,它可能处于:
sudo vi /etc/nginx/nginx.conf
在“服务器{}”部分中添加以下内容(JSON是您的应用程序名称,但通常可以是任何URL应用程序路径,请参见request_URL)):
location /json { include /etc/nginx/fastcgi_params; fastcgi_pass unix:///var/lib/vv/json/sock/sock; }
步骤2 :
最后,重新启动nginx:
sudo systemctl restart nginx
从浏览器访问应用程序服务器
使用以下URL(S)从浏览器等Web客户端访问您的应用程序服务器(使用实际IP代替127.0.0.1,如果有所不同):
#Enter JSON and send for parsing :
http://127.0.0.1/json?req=json_form
将文件cities.json(请参阅文件下)的内容复制到表格中的文本区域。
通过Fetch方法从JavaScript运行
您还可以通过JavaScript/Fetch机制测试JSON解析。首先,在单独的目录中将文件复制到您的Web服务器:
sudo mkdir /var/www/html/velytest
sudo cp post.html /var/www/html/velytest
测试它(使用您的网址而不是127.0.0.1如果不在本地测试):
http://127.0.0.1/velytest/post.html
注意:如果您的服务器在Internet上并且具有防火墙,则可能需要允许HTTP流量 - 请参阅ufw,firewall-cmd等。
文件
您现在已经完成了示例!以下是该项目中的源文件,因此您可以检查其工作原理:
JSON文档(Cities.json)
这是您以解析形式输入的JSON文档。它包含国家,州和城市及其人口。
{ "country": [
{
"name": "USA",
"state": [
{
"name": "Arizona",
"city": [
{
"name" : "Phoenix",
"population": 5000000
} ,
{
"name" : "Tuscon",
"population": 1000000
}
]
} ,
{
"name": "California",
"city": [
{
"name" : "Los Angeles",
"population": 19000000
},
{
"name" : "Irvine"
}
]
}
]
} ,
{
"name": "Mexico",
"state": [
{
"name": "Veracruz",
"city": [
{
"name" : "Xalapa-Enríquez",
"population": 8000000
},
{
"name" : "C\u00F3rdoba",
"population": 220000
}
]
} ,
{
"name": "Sinaloa",
"city": [
{
"name" : "Culiac\u00E1n Rosales",
"population": 3000000
}
]
}
]
}
]
}
来自JavaScript(post.html)的呼叫
您可以通过fetch()从JavaScript调用Vely代码。此HTML文件一旦加载(无需按钮)就可以做到这一点,您当然可以更改它以满足您的需求。这还证明了使用post方法与``应用程序/json''的内容类型的使用来与您的服务器端vely代码交谈。
<!DOCTYPE html>
<html lang="en">
<head>
<title>Vely + JavaScript/Fetch + POST/PUT/PATCH + JSON</title>
</head>
<body>
<h1 class="align">Example: Vely + JavaScript/Fetch + POST/PUT/PATCH + JSON</h1>
<script>
fetch('/json?req=json_process',{
method: 'POST',
headers: {'content-type': 'application/json'},
body: '{ "country": [ \
{ \
"name": "USA", \
"state": [ \
{ \
"name": "Arizona", \
"city": [ \
{ \
"name" : "Phoenix", \
"population": "5000000" \
} , \
{ \
"name" : "Tuscon", \
"population": "1000000" \
} \
\
] \
} , \
{ \
"name": "California", \
"city": [ \
{ \
"name" : "Los Angeles", \
"population": "4000000" \
}, \
{ \
"name" : "Irvine" \
} \
] \
} \
] \
} , \
{ \
"name": "Mexico", \
"state": [ \
{ \
"name": "Veracruz", \
"city": [ \
{ \
"name" : "Xalapa-Enríquez", \
"population": "8000000" \
}, \
{ \
"name" : "C\u00F3rdoba", \
"population": "220000" \
} \
] \
} , \
{ \
"name": "Sinaloa", \
"city": [ \
{ \
"name" : "Culiac\u00E1n Rosales", \
"population": "3000000" \
} \
] \
} \
] \
} \
] \
}'
})
.then((result) => { return result.text(); })
.then((content) => { document.getElementById("json_output").innerHTML = content; });
</script>
<div id='json_output'></div>
</body>
</html>
输入JSON(JSON_FORM.VELY)
这是一个简单的HTML表单,您可以在其中输入JSON文档。由于JSON_PROCESS.VELY和JSON_ALL.VELY中的代码解析了所述的城市列表,因此要输入的文本在cities.json文件中给出。
#include "vely.h"
void json_form () {
out-header default
@<h2>Enter JSON</h2>
@<form action="?req=json_process" method="POST">
@ <label for="json_text">JSON text:</label><br>
@ <textarea name="json_text" rows="8" columns="70">\
</textarea><br/>
@ <button type="submit">Extract specific data</button>
@ <button type="submit" formaction="?req=json_all">\
Extract all data</button>
@ </form>
}
在循环中解析所有JSON数据(JSON_ALL.VELY)
这解析了您可能不知道的结构的文档。获得了每个数据节点,您可以在代码中检查它。
#include "vely.h"
void json_all() {
out-header default
input-param json_text
// Parse json text and display any error and the position of it
new-json define json from json_text status define st \
error-text define etext error-position define epos
if (st != VV_OKAY) {
@Could not parse JSON! Error [<<p-out etext>>] at \
position <<p-num epos>>.
exit-request
}
// Traverse JSON document, node by node, display as a table of
// all data nodes
read-json json traverse begin
@<table border='1'>
while (1)
{
read-json json traverse key define k value define v \
type define t status define s
if (s != VV_OKAY) break;
// Display name, value and type (ignore boolean and type since
// we don't have them)
@<tr>
@<td><<p-out k>></td> <td><<p-out v>></td>
@<td><<p-out t==VV_JSON_TYPE_NUMBER?"Number": \
(t==VV_JSON_TYPE_STRING?"String":"Other")>></td>
@</tr>
}
@</table>
}
通过查找特定元素(json_process.vely)来解析JSON
解析JSON文档。这表明解析您知道的结构但没有固定结构的文档,因此每个元素均可根据其归一化名称检索(请参阅read-json)。
#include "vely.h"
void json_process() {
out-header default
// If JSON data sent via URL-encoded GET or POST
input-param json_text
// If JSON data sent in the request body (application/json),
// use that JSON data
request-body json_body
get-req content-type to define ctype
if (!strcmp(ctype, "application/json")) json_text=json_body;
// Parse json text and display any error and the position of it
new-json define json from json_text status define st \
error-text define etext error-position define epos
if (st != VV_OKAY) {
@Could not parse JSON! Error [<<p-out etext>>] at \
position <<p-num epos>>.
exit-request
}
@Cities found<hr/>
num country_count;
num state_count;
num city_count;
// Start displaying a list
@<ul>
// Look for countries, states and then cities
// Data is organized in hashed arrays, for example
// country[0].state[1].city[0]
// and each can have sub-nodes, such as
// country[0].name
// etc.
for (country_count = 0; ; country_count++) {
// First, build key prefix for a country
(( define json_key_country
@"country"[<<p-num country_count>>]
))
// Search for a country name
(( define json_key_country_name
@<<p-out json_key_country>>."name"
))
// Search for a country name under index [country_count]
read-json json key json_key_country_name \
value define country_name status st
if (st != VV_OKAY) break;
// Country found
@<li>Country: <<p-out country_name>><br/>
@<ul>
// Look for states under this country
for (state_count = 0; ; state_count++) {
// Build key prefix for a state
(( define json_key_state
@<<p-out json_key_country>>."state"[<<p-num state_count>>]
))
// Search for state name
(( define json_key_state_name
@<<p-out json_key_state>>."name"
))
// Search for a state name as:
// country[countr_count].state[state_count]
read-json json key json_key_state_name \
value define state_name status st
if (st != VV_OKAY) break;
// State found
@<li>State: <<p-out state_name>><br/>
@<ul>
// Look for cities under state
for (city_count = 0; ; city_count++) {
// Build key prefix for city
(( define json_key_city
@<<p-out json_key_state>>."city"[<<p-num city_count>>]
))
// Search for city name
(( define json_key_city_name
@<<p-out json_key_city>>."name"
))
// Search for a city name as:
// country[countr_count].state[state_count].
// city[city_count]
read-json json key json_key_city_name \
value define city_name status st
if (st != VV_OKAY) break;
// Found city, get its population
// by building a key for it
(( define json_key_city_population
@<<p-out json_key_city>>."population"
))
// Get city population
read-json json key json_key_city_population \
value define city_population status st
if (st != VV_OKAY) city_population="unknown";
// Display city name and its population
@<li>City:<<p-out city_name>> \
(<<p-out city_population>>)</li>
}
@</ul>
@</li>
}
@</ul>
@</li>
}
@</ul>
}