目录

介绍

背景

安装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转换JSON

JUST是一种转换语言,就像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";elsereturn "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<string> SplitJson(string input,string arrayPath)
  • public static IEnumerable<JObject> 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<string> outputs = JsonTransformer.SplitJson(input, "$.cars.Ford").ToList<string>();

输出将包含4个JSON文件:

string input = File.ReadAllText("Input.json");
List<string> outputs = JsonTransformer.SplitJson(input, "$.cars.Ford").ToList<string>();
{"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 的新类。

JSONXML的示例

从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

<?xml version="1.0" encoding="UTF-8" ?>
<root><root><ifconditiontesttrue>#ifcondition(#valueof($.menu.id.file),csv,#valueof($.menu.value.Window),fail)</ifconditiontesttrue><ifconditiontestfalse>#ifcondition(#valueof($.menu.id.file),xml,#valueof($.menu.value.Window),fail)</ifconditiontestfalse><stringresult><lastindexofand>#lastindexof(#valueof($.stringref),and)</lastindexofand><firstindexofand>#firstindexof(#valueof($.stringref),and)</firstindexofand><subsrting>#substring(#valueof($.stringref),8,10)</subsrting><concat>#concat(#valueof($.menu.id.file),#valueof($.menu.value.Window))</concat></stringresult><mathresult><add>#add(#valueof($.numbers[0]),3)</add><subtract>#subtract(#valueof($.numbers[4]),#valueof($.numbers[0]))</subtract><multiply>#multiply(2,#valueof($.numbers[2]))</multiply><divide>#divide(9,3)</divide></mathresult><conacted>#concatall(#valueof($.d))</conacted><sum>#sum(#valueof($.numbers))</sum><avg>#average(#valueof($.numbers))</avg><min>#min(#valueof($.numbers))</min><max>#max(#valueof($.numbers))</max><arrayconacted>#concatallatpath(#valueof($.x),$.v.a)</arrayconacted><arraysum>#sumatpath(#valueof($.x),$.v.c)</arraysum><arrayavg>#averageatpath(#valueof($.x),$.v.c)</arrayavg><arraymin>#minatpath(#valueof($.x),$.v.b)</arraymin><arraymax>#maxatpath(#valueof($.x),$.v.b)</arraymax></root><FullName>#concat(#concat(#concat(#valueof($.Name), ),#concat(#valueof($.MiddleName), )),#valueof($.Surname))</FullName><Contact_Information><City>#substring(#valueof($.ContactInformation),#add(#firstindexof(#valueof($.ContactInformation),:),1),#subtract(#subtract(#lastindexof(#valueof($.ContactInformation),:),#firstindexof(#valueof($.ContactInformation),:)),1))</City><PhoneNumber>#substring(#valueof($.ContactInformation),#add(#lastindexof(#valueof($.ContactInformation),:),1),#subtract(#lastindexof(#valueof($.ContactInformation),),#lastindexof(#valueof($.ContactInformation),:)))</PhoneNumber><Street_Name>#substring(#valueof($.ContactInformation),0,#firstindexof(#valueof($.ContactInformation),:))</Street_Name></Contact_Information><Personal_Information><Age>#substring(#valueof($.PersonalInformation),0,#firstindexof(#valueof($.PersonalInformation),:))</Age><Ethnicity>#substring(#valueof($.PersonalInformation),#add(#lastindexof(#valueof($.PersonalInformation),:),1),#subtract(#lastindexof(#valueof($.PersonalInformation),),#lastindexof(#valueof($.PersonalInformation),:)))</Ethnicity><LogId>#valueof($.LogId)</LogId><Civil_Status>#substring(#valueof($.PersonalInformation),#add(#firstindexof(#valueof($.PersonalInformation),:),1),#subtract(#subtract(#lastindexof(#valueof($.PersonalInformation),:),#firstindexof(#valueof($.PersonalInformation),:)),1))</Civil_Status></Personal_Information><Custom>#customfunction(JUST.NET.Test,JUST.NET.Test.Season.findseason,#valueof($.tree.branch.leaf),#valueof($.tree.branch.flower))</Custom><iteration>"#loop($.numbers,<!--Record ends here-->)": {<Record><CurrentValue>#currentvalue()</CurrentValue><CurrentIndex>#currentindex()</CurrentIndex><IsLast>#ifcondition(#currentindex(),#lastindex(),yes,no)</IsLast><LastValue>#lastvalue()</LastValue><SomeValue>#valueof($.LogId)</SomeValue></Record>}</iteration>
</root>

输出:

<?xml version="1.0" encoding="UTF-8" ?>
<root><root><ifconditiontesttrue>popup</ifconditiontesttrue><ifconditiontestfalse>fail</ifconditiontestfalse><stringresult><lastindexofand>21</lastindexofand><firstindexofand>6</firstindexofand><subsrting>dveryunuas</subsrting><concat>csvpopup</concat></stringresult><mathresult><add>4</add><subtract>4</subtract><multiply>6</multiply><divide>3</divide></mathresult><conacted>onetwothree</conacted><sum>15</sum><avg>3</avg><min>1</min><max>5</max><arrayconacted>a1,a2,a3b1,b2c1,c2,c3</arrayconacted><arraysum>60</arraysum><arrayavg>20</arrayavg><arraymin>1</arraymin><arraymax>3</arraymax></root><FullName>Kari Inger Nordmann</FullName><Contact_Information><City>Oslo</City><PhoneNumber>88880000</PhoneNumber><Street_Name>Karl johans gate</Street_Name></Contact_Information><Personal_Information><Age>45</Age><Ethnicity>Norwegian</Ethnicity><LogId>5000510625</LogId><Civil_Status>Married</Civil_Status></Personal_Information><Custom>summer</Custom><iteration><Record><CurrentValue>1</CurrentValue><CurrentIndex>0</CurrentIndex><IsLast>no</IsLast><LastValue>5</LastValue><SomeValue>5000510625</SomeValue></Record><!--Record ends here--><Record><CurrentValue>2</CurrentValue><CurrentIndex>1</CurrentIndex><IsLast>no</IsLast><LastValue>5</LastValue><SomeValue>5000510625</SomeValue></Record><!--Record ends here--><Record><CurrentValue>3</CurrentValue><CurrentIndex>2</CurrentIndex><IsLast>no</IsLast><LastValue>5</LastValue><SomeValue>5000510625</SomeValue></Record><!--Record ends here--><Record><CurrentValue>4</CurrentValue><CurrentIndex>3</CurrentIndex><IsLast>no</IsLast><LastValue>5</LastValue><SomeValue>5000510625</SomeValue></Record><!--Record ends here--><Record><CurrentValue>5</CurrentValue><CurrentIndex>4</CurrentIndex><IsLast>yes</IsLast><LastValue>5</LastValue><SomeValue>5000510625</SomeValue></Record><!--Record ends here--></iteration>
</root>

JSONCSV的示例

从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

JUST——简单转换下的JSON相关推荐

  1. 【微信小程序】如何使用阿里巴巴的icon自定义图标以及简单的下拉框组件实现全过程

    前言 小编我将用CSDN记录软件开发之路上所学的心得与知识,有兴趣的小伙伴可以关注一下!也许一个人独行,可以走的很快,但是一群人结伴而行,才能走的更远!让我们在成长的道路上互相学习,让我们共同进步! ...

  2. 简单介绍下我使用了一年多还不知道的Sql server 2005 组件知识

    简介 Microsoft SQL Server 2005 是用于大规模联机事务处理 (OLTP).数据仓库和电子商务应用的数据库平台:也是用于数据集成.分析和报表解决方案的商业智能平台. SQL Se ...

  3. xml转换为json格式时,如何将指定节点转换成数组 Json.NET

    使用Json.NET转换xml成json时,如果xml只有单个节点,但json要求是数组形式[], JsonConvert.SerializeXmlNode 并不能自动识别 示例如下: RecordA ...

  4. R语言转换并保存json文件--使用jsonlite包

    R语言转换并保存json文件--使用jsonlite包 钱亦欣 发表于 2017-07-03 00:10   2477 阅读 http://www.ituring.com.cn/article/468 ...

  5. android读取assets下的.json文件,并且转化为实体类

    创建一个类,用来方法调用.如下,小伙伴用的时候可以直接调用. public class SimulateNetAPI {/*** 获取去最原始的数据信息* @return json data*/pub ...

  6. 简单描述下微信小程序的相关文件类型?

    简单描述下微信小程序的相关文件类型? 微信小程序项目结构主要有四个文件类型,如下: .WXML 是框架设计的一套标签语言,结合基础组件.事件系统,可以构建出页面的结构.内部主要是微信自己定义的一套组件 ...

  7. 下划线JSON字符串与驼峰Java Bean相互转换

    下划线JSON字符串与驼峰Java Bean相互转换 1.实体类 package com.example.springboottest.domain;/*** @author mac* @title: ...

  8. JSONObject转换:简化JSON数据处理的利器

    JSONObject转换:简化JSON数据处理的利器 在现代的软件开发中,处理JSON(JavaScript Object Notation)数据已经成为一项常见的任务.JSON作为一种轻量级的数据交 ...

  9. Example017简单的下拉框

    <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8" ...

最新文章

  1. iOS12-crash错误-reason: 'UITableView failed to obtain a cell from its dataSource'
  2. 解题报告(一)D、(CROC 2016 - Final Round C)Binary Table(矩阵 + 状态压缩 + FWT)(3.5)
  3. CSDN 的文化衫寄送到啦
  4. 第一次来,试发一帖!--ASP.NET 2.0 中的SqlCacheDependency特性
  5. poj 3378 Crazy Thairs
  6. web开发要学多久,HTML表格标签,薪资翻倍
  7. 看完这篇文章,我再也不怕面试官问「垃圾回收」了...
  8. matlab视频旋转振动,基于MATLAB的振动合成及左旋与右旋的动态模拟演示
  9. GPL协议、LGPL协议与BSD协议的法律区别
  10. 扩展JavaScript数组(Array)添加删除元素方法
  11. linux 自动清理var log,Linux 系统 /var/log/journal/ 垃圾日志清理-Fun言
  12. html+车牌号选择,html中车牌号省份简称输入键盘的示例代码
  13. 燃烧远征怀旧服务器人数小程序,《魔兽世界怀旧服》燃烧的远征制作人访谈 详细讲解新版本...
  14. 手机WiFi和热点为何不能同时开
  15. 一个工科土博士生---最近的状态和想法
  16. 微信公众号背景音乐自动播放
  17. 取代公司债电话交易员?高盛新算法可自动提供债券价格
  18. 偷偷爆料下国内比较大型的 IT 软件外包公司名单(2023 最新版!)
  19. 戴尔dell游匣7567笔记本加内存条图文教程
  20. VSM Studio Arduino 数码管显示串口接收数字

热门文章

  1. php取出多维数组的所有元素,php - 获取多维数组PHP中两个元素之间的所有数组 - SO中文参考 - www.soinside.com...
  2. 做春节海报没有思路?传统节日年味十足,PSD分层模板,给你灵感!
  3. 在集设网欣赏灵感作品合集,感受字体之美
  4. 电商促销插画风PSD分层模板,直击底价!吸睛容情!
  5. 学习计划(11.5)
  6. Linux/Document: Livepatch
  7. 十个问题理解Linux epoll工作原理:惊群,
  8. FD.io VPP:用户文档:VPP RPM包的构建与离线安装
  9. 架构设计 之 你为啥只垂直切子系统没分层呢?
  10. xlib/x11:创建一个监测键盘事件的窗口-3-fullscreen-windowed