目录
介绍
背景
安装Nuget包
使用代码
使用JUST转换JSON
valueof
ifcondition
字符串和数学函数
Opearators
聚合函数
多维数组的聚合函数
批量函数
数组循环
嵌套数组循环(在上下文中循环)
数组分组
调用自定义函数
函数嵌套
多个参数和常量函数
检查是否存在
条件转换
动态属性
使用前缀针对多个模式的模式验证
基于数组令牌将JSON拆分为多个JSON(s)
将JSON转换为其他数据格式
JSON到XML的示例
JSON到CSV的示例
链接到测试源代码(源代码现在也可用)
介绍本文介绍如何使用JUST.NET库来转换JSON文档。
背景JUST代表简单转换下的JSON。XSLT是一种使用简单转换语言转换XML文档的非常流行的方法。
现在越来越多的应用程序使用JSON作为数据格式,因为它比XML更简单,体积更小。
但是,没有一种非常简单的方法来转换JSON文档。
我在.NET中创建了一个库,它允许使用非常简单的转换语言转换JSON文档。这是为JSON创建一个XSLT并行程序的尝试。
本文介绍如何使用该库。
安装Nuget包从https://www.nuget.org上下载最新的JUST.NET 。
Install-Package JUST
还提供dotnetcore版本:
Install-Package JUST.NETCore
还提供.NET标准版本。这是从现在开始支持的版本。
Install-Package JUST.NET
使用代码
下载Nuget包后,您将创建一个简单的控制台应用程序。下面是一个简单的C#代码片段,您可以使用它来转换您的JSON:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using JUST;
using System.IO;
namespace JUST.Test
{
public class Program
{
public static void Main(string[] args)
{
string input = File.ReadAllText("Input.json");
string transformer = File.ReadAllText("Transformer.json"); ;
string transformedString = JsonTransformer.Transform(transformer, input);
Console.WriteLine(transformedString);
}
}
}
这里,Input.json是输入JSON文档,而Transformer.json是转换输入JSON的JSON文档。
使用JUST转换JSONJUST是一种转换语言,就像XSLT一样。它包含在转换器JSON内部使用的函数,用于将输入JSON转换为所需的输出JSON。本节介绍JUST中存在的各种函数以及它们如何用于转换JSON。
每个JUST函数都以“#”字符开头。
valueof此函数用于提取给定属性的值。使用属性的JSON路径提取该值。有关如何使用JSON路径的更多信息,请参阅:
- http://www.newtonsoft.com/json/help/html/QueryJsonSelectTokenJsonPath.htm
考虑输入:
{
"menu": {
"popup": {
"menuitem": [
{
"value": "Open",
"onclick": "OpenDoc()"
},
{
"value": "Close",
"onclick": "CloseDoc()"
}
]
}
}
}
转换器:
{
"result": {
"Open": "#valueof($.menu.popup.menuitem[?(@.value=='Open')].onclick)",
"Close": "#valueof($.menu.popup.menuitem[?(@.value=='Close')].onclick)"
}
}
输出:
{
"result":{"Open":"OpenDoc()","Close":"CloseDoc()"}
}
ifcondition
此条件被用于评估if- else的条件。
ifcondition(condition expresson, evaluation expression, true result, false result)
所有四个参数都可以是'valueof'表达式或常量。
考虑输入:
{
"menu": {
"id" : "github",
"repository" : "JUST"
}
}
转换器:
{
"ifconditiontesttrue": "#ifcondition
(#valueof($.menu.id),github,#valueof($.menu.repository),fail)",
"ifconditiontestfalse": "#ifcondition
(#valueof($.menu.id),xml,#valueof($.menu.repository),fail)"
}
输出:
{
"ifconditiontesttrue":"JUST",
"ifconditiontestfalse":"fail"
}
字符串和数学函数
目前,只有基本的和经常使用string和math功能在库中提供。
- lastindexof(input string,search string)
- firstindexof(input string,search string)
- substring(input string,start index,length)
- concat(string 1,string 2)
- add(value 1,value 2)
- subtract(value 1,value 2)
- multiply(value 1,value 2)
- divide(value 1,values 2)
考虑输入:
{
"stringref": "thisisandveryunuasualandlongstring",
"numbers": [ "1", "2", "3", "4", "5" ]
}
转换器:
{
"stringresult": {
"lastindexofand": "#lastindexof(#valueof($.stringref),and)",
"firstindexofand": "#firstindexof(#valueof($.stringref),and)",
"substring": "#substring(#valueof($.stringref),9,11)",
"concat": "#concat(#valueof($.menu.id.file),#valueof($.menu.value.Window))"
},
"mathresult": {
"add": "#add(#valueof($.numbers[0]),3)",
"subtract": "#subtract(#valueof($.numbers[4]),#valueof($.numbers[0]))",
"multiply": "#multiply(2,#valueof($.numbers[2]))",
"divide": "#divide(9,3)"
}
}
输出:
{"stringresult":
{
"lastindexofand":"21",
"firstindexofand":"6",
"substring":"veryunuasua",
"concat":""
},
"mathresult":
{
"add":"4",
"subtract":"4",
"multiply":"6",
"devide":"3"
}
}
Opearators
添加了以下运算符来比较字符串和数字:
- stringequals(string1, string2)
- stringcontains(string1, string2)
- mathequals(decimal1, decimal2)
- mathgreaterthan(decimal1, decimal2)
- mathlessthan(decimal1, decimal2)
- mathgreaterthanorequalto(decimal1, decimal2)
- mathlessthanorequalto(decimal1, decimal2)
考虑输入:
{
"d": [ "one", "two", "three" ],
"numbers": [ "1", "2", "3", "4", "5" ]
}
转换器:
{
"mathresult": {
"third_element_equals_3": "#ifcondition(#mathequals(#valueof($.numbers[2]),3),true,yes,no)",
"third_element_greaterthan_2":
"#ifcondition(#mathgreaterthan(#valueof($.numbers[2]),2),true,yes,no)",
"third_element_lessthan_4":
"#ifcondition(#mathlessthan(#valueof($.numbers[2]),4),true,yes,no)",
"third_element_greaterthanorequals_4":
"#ifcondition(#mathgreaterthanorequalto(#valueof($.numbers[2]),4),true,yes,no)",
"third_element_lessthanoreuals_2":
"#ifcondition(#mathlessthanorequalto(#valueof($.numbers[2]),2),true,yes,no)",
"one_stringequals": "#ifcondition(#stringequals(#valueof($.d[0]),one),true,yes,no)",
"one_stringcontains": "#ifcondition(#stringcontains(#valueof($.d[0]),n),true,yes,no)"
}
}
输出:
{"mathresult": {"third_element_equals_3":"yes","third_element_greaterthan_2":"yes",
"third_element_lessthan_4":"yes","third_element_greaterthanorequals_4":"no",
"third_element_lessthanoreuals_2":"no","one_stringequals":"yes","one_stringcontains":"yes"}}
聚合函数
为一维数组提供以下聚合函数:
- concatall(array)
- sum(array)
- average(array)
- min(array)
- max(array)
Consider the input:-
Consider the input:-
{
"d": [ "one", "two", "three" ],
"numbers": [ "1", "2", "3", "4", "5" ]
}
转换器:
{
"conacted": "#concatall(#valueof($.d))",
"sum": "#sum(#valueof($.numbers))",
"avg": "#average(#valueof($.numbers))",
"min": "#min(#valueof($.numbers))",
"max": "#max(#valueof($.numbers))"
}
输出:
{
"conacted":"onetwothree",
"sum":"15",
"avg":"3",
"min":"1",
"max":"5"
}
多维数组的聚合函数
这些函数与上面的函数基本相同,唯一的区别是您还可以提供指向数组中特定元素的路径:
- concatallatpath(array,path)
- sumatpath(array,path)
- averageatpath(array,path)
- minatpath(array,path)
- maxatpath(array,path)
考虑输入:
{
"x": [
{
"v": {
"a": "a1,a2,a3",
"b": "1",
"c": "10"
}
},
{
"v": {
"a": "b1,b2",
"b": "2",
"c": "20"
}
},
{
"v": {
"a": "c1,c2,c3",
"b": "3",
"c": "30"
}
}
]
}
转换器:
{
"arrayconacted": "#concatallatpath(#valueof($.x),$.v.a)",
"arraysum": "#sumatpath(#valueof($.x),$.v.c)",
"arrayavg": "#averageatpath(#valueof($.x),$.v.c)",
"arraymin": "#minatpath(#valueof($.x),$.v.b)",
"arraymax": "#maxatpath(#valueof($.x),$.v.b)"
}
输出:
{
"arrayconacted":"a1,a2,a3b1,b2c1,c2,c3",
"arraysum":"60",
"arrayavg":"20",
"arraymin":"1",
"arraymax":"3"
}
批量函数
以上所有函数都将属性值设置为输出JSON中的预定义属性。但是,在某些情况下,我们不知道输出会是什么样的,因为它取决于输入。为此提供了批量功能。它们与XSLT中的模板匹配函数相对应。
规则规定的批量函数必须是JSON对象的第一个属性。所有批量函数都表示为属性'#'的数组元素。
这些是截至目前提供的批量函数:
- copy(path)
- replace(path)
- delete(path)
考虑输入:
{
"tree": {
"branch": {
"leaf": "green",
"flower": "red",
"bird": "crow",
"extra": { "twig":"birdnest" }
},
"ladder": {"wood": "treehouse" }
}
}
转换器:
{
"#": [ "#copy($)", "#delete($.tree.branch.bird)",
"#replace($.tree.branch.extra,#valueof($.tree.ladder))" ],
"othervalue" : "othervalue"
}
输出:
{
"othervalue":"othervalue",
"tree":{
"branch":{
"leaf":"green",
"flower":"red",
"extra":{
"wood":"treehouse"
}
},
"ladder":{
"wood":"treehouse"
}
}
}
数组循环
在某些情况下,我们不希望将整个数组复制到目标JSON。我们可能希望将数组转换为不同的格式,或者在设置目标JSON时为每个元素设置一些特殊逻辑。对于这些情况,我们将使用数组循环。
这些是为此目的提供的函数:
- loop(path)——path是要循环的数组的路径
- currentvalue()
- currentvalueatpath(path) ——此处path表示数组内部的路径
- lastvalueatpath(path)——此处path表示数组内部的路径
- currentindex()
- lastindex()
- lastvalue()
考虑输入:
{
"tree": {
"branch": {
"leaf": "green",
"flower": "red",
"bird": "crow",
"extra": { "twig": "birdnest" }
},
"ladder": { "wood": "treehouse" }
},
"numbers": [ "1", "2", "3", "4" ],
"arrayobjects": [
{"country": {"name": "norway","language": "norsk"}},
{
"country": {
"name": "UK",
"language": "english"
}
},
{
"country": {
"name": "Sweden",
"language": "swedish"
}
}]
}
转换器:
{
"iteration": {
"#loop($.numbers)": {
"CurrentValue": "#currentvalue()",
"CurrentIndex": "#currentindex()",
"IsLast": "#ifcondition(#currentindex(),#lastindex(),yes,no)",
"LastValue": "#lastvalue()"
}
},
"iteration2": {
"#loop($.arrayobjects)": {
"CurrentValue": "#currentvalueatpath($.country.name)",
"CurrentIndex": "#currentindex()",
"IsLast": "#ifcondition(#currentindex(),#lastindex(),yes,no)",
"LastValue": "#lastvalueatpath($.country.language)"
}
},
"othervalue": "othervalue"
}
输出:
{
"iteration":[
{"CurrentValue":"1","CurrentIndex":"0",
"IsLast":"no","LastValue":"4"},
{"CurrentValue":"2","CurrentIndex":"1",
"IsLast":"no","LastValue":"4"},
{"CurrentValue":"3","CurrentIndex":"2",
"IsLast":"no","LastValue":"4"},
{"CurrentValue":"4","CurrentIndex":"3",
"IsLast":"yes","LastValue":"4"}
],
"iteration2":[
{"CurrentValue":"norway","CurrentIndex":"0",
"IsLast":"no","LastValue":"swedish"},
{"CurrentValue":"UK","CurrentIndex":"1",
"IsLast":"no","LastValue":"swedish"},
{"CurrentValue":"Sweden","CurrentIndex":"2",
"IsLast":"yes","LastValue":"swedish"}
],
"othervalue":"othervalue"
}
嵌套数组循环(在上下文中循环)
引入了一个新函数loopwithincontext ,其可以循环使用外部循环的上下文。
考虑输入:
{
"NestedLoop": {
"Organization": {
"Employee": [
{
"Name": "E2",
"Details": [
{
"Country": "Iceland",
"Age": "30",
"Name": "Sven",
"Language": "Icelandic"
}
]
},
{
"Name": "E1",
"Details": [
{
"Country": "Denmark",
"Age": "30",
"Name": "Svein",
"Language": "Danish"
}
]
}
]
}
}
}
转换器:
{
"hello": {
"#loop($.NestedLoop.Organization.Employee)": {
"CurrentName": "#currentvalueatpath($.Name)",
"Details": {
"#loopwithincontext($.Details)": {
"CurrentCountry": "#currentvalueatpath($.Country)"
}
}
}
}
}
输出:
{
"hello":[
{
"CurrentName":"E2",
"Details":[
{
"CurrentCountry":"Iceland"
}
]
},
{
"CurrentName":"E1",
"Details":[
{
"CurrentCountry":"Denmark"
}
]
}
]
}
数组分组
引入了类似于SQL GROUP BY子句的函数,以根据元素的值对数组进行分组。
grouparrayby(path,groupingElementName,groupedElementName)
输入:
{
"Forest": [
{
"type": "Mammal",
"qty": 1,
"name": "Hippo"
},
{
"type": "Bird",
"qty": 2,
"name": "Sparrow"
},
{
"type": "Amphibian",
"qty": 300,
"name": "Lizard"
},
{
"type": "Bird",
"qty": 3,
"name": "Parrot"
},
{
"type": "Mammal",
"qty": 1,
"name": "Elephant"
},
{
"type": "Mammal",
"qty": 10,
"name": "Dog"
}
]
}
转换器:
{
"Result": "#grouparrayby($.Forest,type,all)"
}
输出:
{
"Result":[
{
"type":"Mammal",
"all":[
{
"qty":1,
"name":"Hippo"
},
{
"qty":1,
"name":"Elephant"
},
{
"qty":10,
"name":"Dog"
}
]
},
{
"type":"Bird",
"all":[
{
"qty":2,
"name":"Sparrow"
},
{
"qty":3,
"name":"Parrot"
}
]
},
{
"type":"Amphibian",
"all":[
{
"qty":300,
"name":"Lizard"
}
]
}
]
}
您可以使用多个“分组元素”进行分组。它们应该用冒号(:)分隔。
考虑以下输入:
{
"Vehicle": [
{
"type": "air",
"company": "Boeing",
"name": "airplane"
},
{
"type": "air",
"company": "Concorde",
"name": "airplane"
},
{
"type": "air",
"company": "Boeing",
"name": "Chopper"
},
{
"type": "land",
"company": "GM",
"name": "car"
},
{
"type": "sea",
"company": "Viking",
"name": "ship"
},
{
"type": "land",
"company": "GM",
"name": "truck"
}
]
}
转换器:
{
"Result": "#grouparrayby($.Vehicle,type:company,all)"
}
输出:
{
"Result":[
{
"type":"air",
"company":"Boeing",
"all":[
{
"name":"airplane"
},
{
"name":"Chopper"
}
]
},
{
"type":"air",
"company":"Concorde",
"all":[
{
"name":"airplane"
}
]
},
{
"type":"land",
"company":"GM",
"all":[
{
"name":"car"
},
{
"name":"truck"
}
]
},
{
"type":"sea",
"company":"Viking",
"all":[
{
"name":"ship"
}
]
}
]
}
调用自定义函数
您可以在C#中创建自己的自定义函数,并从转换器JSON中调用它们。自定义函数必须驻留在public 类中,并且必须是public static方法。
使用以下语法调用自定义函数:
#customfunction(dll name, FQN for the static function, argument1.......,argumentN)
考虑以下输入:
{
"tree": {
"branch": {
"leaf": "green",
"flower": "red",
"bird": "crow"
}
}
}
转换器:
{
"Season": "#customfunction(JUST.NET.Test,JUST.NET.Test.Season.findseason,
#valueof($.tree.branch.leaf),#valueof($.tree.branch.flower))"
}
自定义功能:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JUST.NET.Test
{
public class Season
{
public static string findseason(string leafColour, string flowerColour)
{
if (leafColour == "green" && flowerColour == "red")
return "summer";
else
return "winter";
}
}
}
输出:
{"Season":"summer"}
函数嵌套
您可以轻松地嵌套函数以执行复杂的转换。
以下示例演示了此类转换的示例:
考虑以下输入:
{
"Name": "Kari",
"Surname": "Nordmann",
"MiddleName": "Inger",
"ContactInformation": "Karl johans gate:Oslo:88880000" ,
"PersonalInformation": "45:Married:Norwegian"
}
转换器:
{
"FullName": "#concat(#concat
(#concat(#valueof($.Name), ),#concat(#valueof($.MiddleName), )),#valueof($.Surname))",
"Contact Information": {
"Street Name": "#substring(#valueof($.ContactInformation),
0,#firstindexof(#valueof($.ContactInformation),:))",
"City": "#substring(#valueof($.ContactInformation),#add(#firstindexof
(#valueof($.ContactInformation),:),1),#subtract(#subtract
(#lastindexof(#valueof($.ContactInformation),:),#firstindexof
(#valueof($.ContactInformation),:)),1))",
"PhoneNumber": "#substring
(#valueof($.ContactInformation),#add(#lastindexof
(#valueof($.ContactInformation),:),1),#subtract
(#lastindexof(#valueof($.ContactInformation),),#lastindexof
(#valueof($.ContactInformation),:)))"
},
"Personal Information": {
"Age": "#substring(#valueof($.PersonalInformation),
0,#firstindexof(#valueof($.PersonalInformation),:))",
"Civil Status": "#substring(#valueof
($.PersonalInformation),#add(#firstindexof
(#valueof($.PersonalInformation),:),1),#subtract(#subtract
(#lastindexof(#valueof($.PersonalInformation),:),#firstindexof
(#valueof($.PersonalInformation),:)),1))",
"Ethnicity": "#substring(#valueof
($.PersonalInformation),#add(#lastindexof
(#valueof($.PersonalInformation),:),1),#subtract(#lastindexof
(#valueof($.PersonalInformation),),#lastindexof
(#valueof($.PersonalInformation),:)))"
}
输出:
{
"FullName":"Kari Inger Nordmann",
"Contact Information":{
"Street Name":"Karl johans gate",
"City":"Oslo",
"PhoneNumber":"88880000"
},
"Personal Information":{
"Age":"45",
"Civil Status":"Married",
"Ethnicity":"Norwegian"
}
}
多个参数和常量函数
上述场景中的转换看起来相当复杂。当string变得更长时,它会变得非常混乱。此外,由于逗号(,)是保留关键字,因此无法将逗号连接到string。
因此,引入了以下3个函数:
- xconcat(string1,string2......stringx)——连接多个strings
- xadd(int1,int2......intx)——添加多个整数
- constant_comma() ——返回逗号(,)
- constant_hash() ——返回哈希(#)
考虑以下输入:
{
"Name": "Kari",
"Surname": "Nordmann",
"MiddleName": "Inger",
"ContactInformation": "Karl johans gate:Oslo:88880000" ,
"PersonalInformation": "45:Married:Norwegian"
}
转换器:
{
"FullName": "#xconcat(#valueof($.Name),
#constant_comma(),#valueof($.MiddleName),
#constant_comma(),#valueof($.Surname))",
"AgeOfParents":
"#xadd(#valueof($.AgeOfMother),#valueof($.AgeOfFather))"
}
输出:
{"FullName":"Kari,Inger,Nordmann",
"AgeOfParents":"67"}
检查是否存在
添加了以下两个函数来检查是否存在:
- exists(path)
- existsandnotempty(path)
考虑以下输入:
{
"BuyDate": "2017-04-10T11:36:39+03:00",
"ExpireDate": ""
}
转换器:
{
"BuyDateString": "#ifcondition(#exists($.BuyDate),
true,#concat(Buy Date : ,#valueof($.BuyDate)),NotExists)",
"BuyDateString2": "#ifcondition(#existsandnotempty($.BuyDate),
true,#concat(Buy Date : ,#valueof($.BuyDate)),EmptyOrNotExists)",
"ExpireDateString": "#ifcondition(#exists($.ExpireDate),
true,#concat(Expire Date : ,#valueof($.ExpireDate)),NotExists)",
"ExpireDateString2": "#ifcondition(#existsandnotempty($.ExpireDate),
true,#concat(Expire Date : ,#valueof($.ExpireDate)),EmptyOrNotExists)",
"SellDateString": "#ifcondition(#exists($.SellDate),
true,#concat(Sell Date : ,#valueof($.SellDate)),NotExists)",
"SellDateString2": "#ifcondition(#existsandnotempty($.SellDate),
true,#concat(Sell Date : ,#valueof($.SellDate)),EmptyOrNotExists)"
}
输出:
{
"BuyDateString":"Buy Date : 2017-04-10T11:36:39+03:00",
"BuyDateString2":"Buy Date : 2017-04-10T11:36:39+03:00",
"ExpireDateString":"Expire Date : ",
"ExpireDateString2":"EmptyOrNotExists",
"SellDateString":"NotExists",
"SellDateString2":"EmptyOrNotExists"
}
条件转换
使用ifgroup 函数可以实现条件转换。
该函数将表达式作为参数,该值应该计算为布尔值。
考虑以下输入:
{
"Tree": {
"Branch": "leaf",
"Flower": "Rose"
}
}
转换器:
{
"Result": {
"Header": "JsonTransform",
"#ifgroup(#exists($.Tree.Branch))": {
"State": {
"Value1": "#valueof($.Tree.Branch)",
"Value2": "#valueof($.Tree.Flower)"
}
}
}
}
输出:
{
"Result":{
"Header":"JsonTransform",
"State":{
"Value1":"leaf",
"Value2":"Rose"
}
}
}
现在,对于相同的输入,如果我们使用以下转换器,我们会得到不同的输出。
转换器:
{
"Result": {
"Header": "JsonTransform",
"#ifgroup(#exists($.Tree.Root))": {
"State": {
"Value1": "#valueof($.Tree.Branch)",
"Value2": "#valueof($.Tree.Flower)"
}
}
}
}
输出:
{
"Result":{
"Header":"JsonTransform"
}
}
动态属性
我们现在可以使用eval 函数创建动态属性。该函数将表达式作为参数。
考虑以下输入:
{
"Tree": {
"Branch": "leaf",
"Flower": "Rose"
}
}
转换器:
{
"Result": {
"#eval(#valueof($.Tree.Flower))": "x"
}
}
输出:
{
"Result":{
"Rose":"x"
}
}
使用前缀针对多个模式的模式验证
在新的Nuget 2.0.XX中引入了一个新功能,用于针对多个模式验证JSON。这是为了使用XSD中的前缀启用基于名称空间的验证。
下面是一个示例代码,您需要编写该代码以使用前缀来针对2个模式验证JSON:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using JUST;
using System.IO;
namespace JUST.Test
{
public class Program
{
public static void Main(string[] args)
{
string inputJson = File.ReadAllText("ValidationInput.json")//read input from JSON file.;
string schemaJsonX = File.ReadAllText("SchemaX.json")//read first schema from JSON file.;
string schemaJsonY = File.ReadAllText("SchemaY.json")//read second input from JSON file.;
JsonValidator validator = new JsonValidator(inputJson)//create instance
//of JsonValidator using the input.;
validator.AddSchema("x", schemaJsonX)//Add first schema with prefix 'x'.;
validator.AddSchema("y", schemaJsonY)//Add second schema with prefix 'y'.;
validator.Validate();
}
}
}
在上述情况下,如果验证不成功,将引发验证错误的异常。
考虑验证输入:
{
"x.tree": { "x.branch": { "x.leaf": "1" } },
"x.child": 1,
"y.animal": 1
}
模式X JSON:
{
"properties": {
"tree": {
"type": "object",
"properties": {
"branch": {
"type": "object",
"properties": {
"leaf": { "type": "string" }
}
}
}
},
"child": { "type": "string" }
}
}
模式Y JSON:
{
"properties": {
"animal": { "type": "string" }
}
}
上述情况中抛出的异常消息是:
Unhandled Exception: System.Exception: Invalid type. Expected String but got Integer.
Path '['x.child']', line 3, position 14. AND Invalid type. Expected String but got Integer.
Path '['y.animal']', line 4, position 15.
基于数组令牌将JSON拆分为多个JSON(s)
现在可以将包含数组的JSON文件拆分为多个JSON文件,每个文件代表每个数组元素的文件。
为此目的增加了两个新功能:
- public static IEnumerable SplitJson(string input,string arrayPath)
- public static IEnumerable SplitJson(JObject input, string arrayPath)
考虑输入:
{
"cars": {
"Ford": [
{
"model": "Taurus",
"doors": 4
},
{
"model": "Escort",
"doors": 4
},
{
"model": "Fiesta",
"doors": 3
},
{
"model": "Bronco",
"doors": 5
}
],
"firstName": "John",
"lastName": "Smith",
}
}
下面是一个示例代码,它分割了上面的输入:
string input = File.ReadAllText("Input.json");
List outputs = JsonTransformer.SplitJson(input, "$.cars.Ford").ToList();
输出将包含4个JSON文件:
string input = File.ReadAllText("Input.json");
List outputs = JsonTransformer.SplitJson(input, "$.cars.Ford").ToList();
{"cars":{"Ford":{"model":"Escort",
"doors":4},"firstName":"John","lastName":"Smith"}}
{"cars":{"Ford":{"model":"Fiesta",
"doors":3},"firstName":"John","lastName":"Smith"}}
{"cars":{"Ford":{"model":"Bronco",
"doors":5},"firstName":"John","lastName":"Smith"}}
将JSON转换为其他数据格式
JUST.NET现在也可以将JSON数据转换为其他通用格式。此特征支持除BULK FUNCTIONS 以外的所有函数。
#loop函数接受一个额外的参数,该参数定义各个记录之间的分隔符。
#loop(path,seaperator).
如果未定义分隔符,则使用默认分隔符NEWLINE。
已为此新功能引入了一个名为DataTransformer 的新类。
JSON到XML的示例从JSON转换为XML的示例代码:
string input = File.ReadAllText("Input.json");
string transformer = File.ReadAllText("DataTransformer.xml");
string transformedString = DataTransformer.Transform(transformer, input);
Input.json:
{
"menu": {
"id": {
"file": "csv"
},
"value": {
"Window": "popup"
},
"popup": {
"menuitem": [
{
"value": "New",
"onclick": {
"action": "CreateNewDoc()"
}
},
{
"value": "Open",
"onclick": "OpenDoc()"
},
{
"value": "Close",
"onclick": "CloseDoc()"
}
]
}
},
"x": [
{
"v": {
"a": "a1,a2,a3",
"b": "1",
"c": "10"
}
},
{
"v": {
"a": "b1,b2",
"b": "2",
"c": "20"
}
},
{
"v": {
"a": "c1,c2,c3",
"b": "3",
"c": "30"
}
}
],
"stringref": "thisisandveryunuasualandlongstring",
"d": [ "one", "two", "three" ],
"numbers": [ "1", "2", "3", "4", "5" ],
"tree": {
"branch": {
"leaf": "green",
"flower": "red",
"bird": "crow"
}
},
"Name": "Kari",
"Surname": "Nordmann",
"MiddleName": "Inger",
"ContactInformation": "Karl johans gate:Oslo:88880000",
"PersonalInformation": "45:Married:Norwegian",
"AgeOfMother": "67",
"AgeOfFather": "70",
"BuyDate": "2017-04-10T11:36:39+03:00",
"ExpireDate": "",
"LogId": 5000510625
}
DataTransformer.xml:
#ifcondition(#valueof($.menu.id.file),csv,
#valueof($.menu.value.Window),fail)
#ifcondition(#valueof($.menu.id.file),xml,
#valueof($.menu.value.Window),fail)
#lastindexof(#valueof($.stringref),and)
#firstindexof(#valueof($.stringref),and)
#substring(#valueof($.stringref),8,10)
#concat(#valueof($.menu.id.file),#valueof($.menu.value.Window))
#add(#valueof($.numbers[0]),3)
#subtract(#valueof($.numbers[4]),#valueof($.numbers[0]))
#multiply(2,#valueof($.numbers[2]))
#divide(9,3)
#concatall(#valueof($.d))
#sum(#valueof($.numbers))
#average(#valueof($.numbers))
#min(#valueof($.numbers))
#max(#valueof($.numbers))
#concatallatpath(#valueof($.x),$.v.a)
#sumatpath(#valueof($.x),$.v.c)
#averageatpath(#valueof($.x),$.v.c)
#minatpath(#valueof($.x),$.v.b)
#maxatpath(#valueof($.x),$.v.b)
#concat(#concat(#concat(#valueof($.Name), ),
#concat(#valueof($.MiddleName), )),#valueof($.Surname))
#substring(#valueof($.ContactInformation),#add(#firstindexof
(#valueof($.ContactInformation),:),1),
#subtract(#subtract(#lastindexof(#valueof($.ContactInformation),:),
#firstindexof(#valueof($.ContactInformation),:)),1))
#substring(#valueof($.ContactInformation),
#add(#lastindexof(#valueof($.ContactInformation),:),1),
#subtract(#lastindexof(#valueof($.ContactInformation),),
#lastindexof(#valueof($.ContactInformation),:)))
#substring(#valueof($.ContactInformation),0,
#firstindexof(#valueof($.ContactInformation),:))
#substring(#valueof($.PersonalInformation),0,
#firstindexof(#valueof($.PersonalInformation),:))
#substring(#valueof($.PersonalInformation),
#add(#lastindexof(#valueof($.PersonalInformation),:),1),
#subtract(#lastindexof(#valueof($.PersonalInformation),),
#lastindexof(#valueof($.PersonalInformation),:)))
#valueof($.LogId)
#substring(#valueof($.PersonalInformation),
#add(#firstindexof(#valueof($.PersonalInformation),:),1),
#subtract(#subtract(#lastindexof(#valueof($.PersonalInformation),:),
#firstindexof(#valueof($.PersonalInformation),:)),1))
#customfunction(JUST.NET.Test,JUST.NET.Test.Season.findseason,
#valueof($.tree.branch.leaf),#valueof($.tree.branch.flower))
"#loop($.numbers,)": {
#currentvalue()
#currentindex()
#ifcondition(#currentindex(),#lastindex(),yes,no)
#lastvalue()
#valueof($.LogId)
}
输出:
popup
fail
21
6
dveryunuas
csvpopup
4
4
6
3
onetwothree
15
3
1
5
a1,a2,a3b1,b2c1,c2,c3
60
20
1
3
Kari Inger Nordmann
Oslo
88880000
Karl johans gate
45
Norwegian
5000510625
Married
summer
1
0
no
5
5000510625
2
1
no
5
5000510625
3
2
no
5
5000510625
4
3
no
5
5000510625
5
4
yes
5
5000510625
JSON到CSV的示例
从JSON转换为CSV的示例代码:
string transformer = File.ReadAllText("Input.json");
string transformer = File.ReadAllText("DataTransformer.csv");
string transformedString = DataTransformer.Transform(transformer, input);
输入文件与XML示例相同。
"#loop($.numbers)": {#currentvalue(),#currentindex(),
#ifcondition(#currentindex(),#lastindex(),yes,no),#lastvalue(),#valueof($.LogId)}
输出:
1,0,no,5,5000510625
2,1,no,5,5000510625
3,2,no,5,5000510625
4,3,no,5,5000510625
5,4,yes,5,5000510625
链接到测试源代码(源代码现在也可用)
我创建了一个包含C#项目的GitHub存储库,并在输入JSON文件上有各种转换方案。
- https://github.com/WorkMaze/JUST.net
我希望您可以使用JUST来转换JSON文档。
原文地址:https://www.codeproject.com/Articles/1187172/JUST-JSON-Under-Simple-Transformation