diff --git a/Examples/DataTransformer.csv b/Examples/DataTransformer.csv deleted file mode 100644 index ac6f641..0000000 --- a/Examples/DataTransformer.csv +++ /dev/null @@ -1 +0,0 @@ -"#loop($.numbers)": {#currentvalue(),#currentindex(),#ifcondition(#currentindex(),#lastindex(),yes,no),#lastvalue(),#valueof($.LogId)} \ No newline at end of file diff --git a/Examples/DataTransformer.xml b/Examples/DataTransformer.xml deleted file mode 100644 index fefa1a7..0000000 --- a/Examples/DataTransformer.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - #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) - } - - - \ No newline at end of file diff --git a/Examples/Input.json b/Examples/Input.json deleted file mode 100644 index 3b5e9fc..0000000 --- a/Examples/Input.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "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" - } - }, - "season": { - "characteristics": { - "hot": true, - "averageDaysOfRain": 10, - "randomDay": "2018-08-01T00:00:00.000Z" - } - }, - "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, - "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" - } - ] - } - ] - } - }, - "people": [ - { - "name": "Jim", - "phoneNumbers": [ - { - "type": "iPhone", - "number": "0123-4567-8888", - "countryPrefix": "34" - }, - { - "type": "work", - "number": "012567-8910" - } - ] - }, - { - "name": "John", - "phoneNumbers": [ - { - "type": "iPhone", - "number": "0123-4562347-8888", - "countryPrefix": "43" - }, - { - "type": "home", - "number": "0134523-4567-8910" - } - ] - }, - { - "name": "John" - } - ], - "PhoneTypeToSearch": "iPhone", - "DataForArrayTransformer": { - "Field1": "Value1", - "Field2": "Value2" - } -} \ No newline at end of file diff --git a/Examples/InputDynamic.json b/Examples/InputDynamic.json deleted file mode 100644 index 7069fc7..0000000 --- a/Examples/InputDynamic.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "Tree": { - "Branch": "leaf", - "Flower": "Rose" - } -} \ No newline at end of file diff --git a/Examples/InputSpecial.json b/Examples/InputSpecial.json deleted file mode 100644 index edb618a..0000000 --- a/Examples/InputSpecial.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "cardExpire": "09/2019", - "orderPlaceDateLong": "Tue 10 October 2017", - "shippingAddress2": "#F370 F370", - "shippingAddressZip": "\\33486-2159", - "shippingAddress1": "1231 NW 13th St Apt 370F", - "orderTotal": "22.48", - "cardType": "Visa", - "orderShipping": "0.00", - "shippingLastName": "Doe", - "shippingFirstName": "Jane", - "orderSubtotal": "22.48", - "shippingAddressTown": "Boca Raton", - "firstName": "Jane", - "lastName": "Doe", - "orderPlaceDateShort": "10/10/2017", - "shippingAdressState": null, - "orderTotalSavings": "2.50" -} \ No newline at end of file diff --git a/Examples/InputToSplit.json b/Examples/InputToSplit.json deleted file mode 100644 index 9b1e275..0000000 --- a/Examples/InputToSplit.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "cars": { - "Ford": [ - { - "model": "Taurus", - "doors": 4 - }, - { - "model": "Escort", - "doors": 4 - }, - { - "model": "Fiesta", - "doors": 3 - }, - { - "model": "Bronco", - "doors": 5 - } - ], - "firstName": "John", - "lastName": "Smith", - "age": 25, - "address": { - "streetAddress": "21 2nd Street", - "city": "New York", - "state": "NY", - "postalCode": "10021" - }, - "phoneNumber": [ - { - "type": "home", - "number": "212 555-1234" - }, - { - "type": "fax", - "number": "646 555-4567" - } - ] - - } -} \ No newline at end of file diff --git a/Examples/Input_Unordered.json b/Examples/Input_Unordered.json deleted file mode 100644 index f9eedff..0000000 --- a/Examples/Input_Unordered.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "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" - } - - - ] -} \ No newline at end of file diff --git a/Examples/Input_Unordered_2.json b/Examples/Input_Unordered_2.json deleted file mode 100644 index bcbd87d..0000000 --- a/Examples/Input_Unordered_2.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "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" - } - - - ] - -} \ No newline at end of file diff --git a/Examples/SchemaX.json b/Examples/SchemaX.json deleted file mode 100644 index d50446d..0000000 --- a/Examples/SchemaX.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "properties": { - "tree": { - "type": "object", - "properties": { - "branch": { - "type": "object", - "properties": { - "leaf": { "type": "string" } - } - } - } - }, - "child": { "type": "string" } - } -} diff --git a/Examples/SchemaY.json b/Examples/SchemaY.json deleted file mode 100644 index f847a42..0000000 --- a/Examples/SchemaY.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "properties": { - "animal": { "type": "string" } - } -} diff --git a/Examples/TransformDynamic.json b/Examples/TransformDynamic.json deleted file mode 100644 index 28ab874..0000000 --- a/Examples/TransformDynamic.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "Result": { - "Header": "JsonTransform", - "#ifgroup(#exists($.Tree.Branch))": { - "State": { - "Value1": "#valueof($.Tree.Branch)", - "Value2": "#valueof($.Tree.Flower)" - } - }, - "#eval(#valueof($.Tree.Flower))": "x", - "#ifgroup(#exists($.Tree.Flower))": { - "Comment": { - "Statement": "Flower Exists" - } - } - } - -} \ No newline at end of file diff --git a/Examples/Transform_Unordered.json b/Examples/Transform_Unordered.json deleted file mode 100644 index 9d5fbf5..0000000 --- a/Examples/Transform_Unordered.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "Result": "#grouparrayby($.Forest,type,all)" -} \ No newline at end of file diff --git a/Examples/Transform_Unordered_2.json b/Examples/Transform_Unordered_2.json deleted file mode 100644 index 0cbf0b4..0000000 --- a/Examples/Transform_Unordered_2.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "Result": "#grouparrayby($.Vehicle,type:company,all)" - - -} \ No newline at end of file diff --git a/Examples/Transformer.json b/Examples/Transformer.json deleted file mode 100644 index 9c81647..0000000 --- a/Examples/Transformer.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "#": [ "#copy($)", "#copy($.menu.id)", "#copy($.menu.value)", "#delete($.menu.popup)", "#replace($.menu.id,#valueof($.menu.value))" ], - "root": { - "menu1": "#valueof($.menu.popup.menuitem[?(@.value=='New')].onclick)", - "menu2": "#valueof($.menu.popup.menuitem[?(@.value=='Open')].onclick)", - "array": { - "fullarray": "#valueof($.x)", - "arrayelement": "#valueof($.x[0])", - "specificelement": "#valueof($.x[1].v.a)" - }, - "ifconditiontesttrue": "#ifcondition(#valueof($.menu.id.file),csv,#valueof($.menu.value.Window),fail)", - "ifconditiontestfalse": "#ifcondition(#valueof($.menu.id.file),xml,#valueof($.menu.value.Window),fail)", - "stringresult": { - "lastindexofand": "#lastindexof(#valueof($.stringref),and)", - "firstindexofand": "#firstindexof(#valueof($.stringref),and)", - "subsrting": "#substring(#valueof($.stringref),8,10)", - "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)" - }, - "conacted": "#concatall(#valueof($.d))", - "sum": "#sum(#valueof($.numbers))", - "avg": "#average(#valueof($.numbers))", - "min": "#min(#valueof($.numbers))", - "max": "#max(#valueof($.numbers))", - "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)" - }, - - "iteration": { - "#loop($.numbers)": { - "CurrentValue": "#currentvalue()", - "CurrentIndex": "#currentindex()", - "IsLast": "#ifcondition(#currentindex(),#lastindex(),yes,no)", - "LastValue": "#lastvalue()" - - } - }, - "iteration2": { - "#loop($.x)": { - "CurrentValue": "#currentvalueatpath($.v.a)", - "CurrentIndex": "#currentindex()", - "IsLast": "#ifcondition(#currentindex(),#lastindex(),yes,no)", - "LastValue": "#lastvalueatpath($.v.b)" - - } - }, - "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),:)))", - "LogId": "#valueof($.LogId)" - }, - -} \ No newline at end of file diff --git a/Examples/Transformer_Existance.json b/Examples/Transformer_Existance.json deleted file mode 100644 index cff52ea..0000000 --- a/Examples/Transformer_Existance.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "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)" -} \ No newline at end of file diff --git a/Examples/Transformer_Math.json b/Examples/Transformer_Math.json deleted file mode 100644 index ef99f56..0000000 --- a/Examples/Transformer_Math.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "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)", - "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)" - } -} diff --git a/Examples/Transformer_aggregate.json b/Examples/Transformer_aggregate.json deleted file mode 100644 index 2e3d3ac..0000000 --- a/Examples/Transformer_aggregate.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "conacted": "#concatall(#valueof($.d))", - "sum": "#sum(#valueof($.numbers))", - "avg": "#average(#valueof($.numbers))", - "min": "#min(#valueof($.numbers))", - "max": "#max(#valueof($.numbers))" -} diff --git a/Examples/Transformer_array.json b/Examples/Transformer_array.json deleted file mode 100644 index e943566..0000000 --- a/Examples/Transformer_array.json +++ /dev/null @@ -1,8 +0,0 @@ -[ - { - "field": "#valueof($.DataForArrayTransformer.Field1)" - }, - { - "field": "#valueof($.DataForArrayTransformer.Field2)" - } -] \ No newline at end of file diff --git a/Examples/Transformer_arrayaggregate.json b/Examples/Transformer_arrayaggregate.json deleted file mode 100644 index 0687f18..0000000 --- a/Examples/Transformer_arrayaggregate.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "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)" -} diff --git a/Examples/Transformer_copy.json b/Examples/Transformer_copy.json deleted file mode 100644 index 627be9c..0000000 --- a/Examples/Transformer_copy.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "#": [ "#copy($.menu.id)", "#copy($.menu.value)" ], -} \ No newline at end of file diff --git a/Examples/Transformer_customfunction.json b/Examples/Transformer_customfunction.json deleted file mode 100644 index 39cf35b..0000000 --- a/Examples/Transformer_customfunction.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "Season": "#customfunction(JUST.NET.Test,JUST.NET.Test.Season.findseason,#valueof($.tree.branch.leaf),#valueof($.tree.branch.flower))" -} diff --git a/Examples/Transformer_customfunctionspecial.json b/Examples/Transformer_customfunctionspecial.json deleted file mode 100644 index fbe54fc..0000000 --- a/Examples/Transformer_customfunctionspecial.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "Season": "#customfunction(JUST.NET.Test,JUST.NET.Test.Season.serialize,#valueof($))" -} \ No newline at end of file diff --git a/Examples/Transformer_delete.json b/Examples/Transformer_delete.json deleted file mode 100644 index 29127ab..0000000 --- a/Examples/Transformer_delete.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "#": [ "#copy($)", "#delete($.menu.popup)", "#delete($.x)" ] -} diff --git a/Examples/Transformer_externalmethods.json b/Examples/Transformer_externalmethods.json deleted file mode 100644 index 9da4549..0000000 --- a/Examples/Transformer_externalmethods.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "externalStaticMethodResult": "#ExternalMethods::ExternalMethods.ExternalClass::StaticMethod()", - "externalStaticTypedParametersResult": "#ExternalMethods::ExternalMethods.ExternalClass::StaticTypedParameters(1,true,abc,2018-10-11T11:00:00.000Z)", - "externalInstanceMethodResult": "#ExternalMethods::ExternalMethods.ExternalClass::InstanceMethod()", - "externalInstanceTypedParametersResult": "#ExternalMethods::ExternalMethods.ExternalClass::TypedParameters(1,true,abc,2018-10-11T11:00:00.000Z)", - "externalInstanceNavigateTypedParametersResult": "#ExternalMethods::ExternalMethods.ExternalClass::NavigateTypedParameters(#valueof($.season.characteristics.hot))", - - "internalStaticMethodResult": "#InternalMethods.InternalClass::StaticMethod()", - "internalStaticTypedParametersResult": "#InternalMethods.InternalClass::StaticTypedParameters(1,true,abc,2018-10-11T11:00:00.000Z)", - "internalInstanceMethodResult": "#InternalMethods.InternalClass::InstanceMethod()", - "internalInstanceTypedParametersResult": "#InternalMethods.InternalClass::TypedParameters(1,true,abc,2018-10-11T11:00:00.000Z)", - "internalInstanceNavigateTypedParametersResult": "#InternalMethods.InternalClass::NavigateTypedParameters(#valueof($.season))", - - "summer": "#ExternalMethods::SeasonsHelper.Season::IsSummer(#valueof($.season.characteristics.hot),#valueof($.season.characteristics.averageDaysOfRain),#valueof($.season.characteristics.randomDay))" -} diff --git a/Examples/Transformer_ifcondition.json b/Examples/Transformer_ifcondition.json deleted file mode 100644 index 873ea7d..0000000 --- a/Examples/Transformer_ifcondition.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "ifconditiontesttrue": "#ifcondition(#valueof($.menu.id.file),csv,#valueof($.menu.value.Window),fail)", - "ifconditiontestfalse": "#ifcondition(#valueof($.menu.id.file),xml,#valueof($.menu.value.Window),fail)" -} diff --git a/Examples/Transformer_looping.json b/Examples/Transformer_looping.json deleted file mode 100644 index caf6595..0000000 --- a/Examples/Transformer_looping.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - - "iteration": { - "#loop($.numbers)": { - "CurrentValue": "#currentvalue()", - "CurrentIndex": "#currentindex()", - "IsLast": "#ifcondition(#currentindex(),#lastindex(),yes,no)", - "LastValue": "#lastvalue()" - - } - }, - "iteration2": { - "#loop($.x)": { - "CurrentValue": "#currentvalueatpath($.v.a)", - "CurrentIndex": "#currentindex()", - "IsLast": "#ifcondition(#currentindex(),#lastindex(),yes,no)", - "LastValue": "#lastvalueatpath($.v.b)" - - } - }, - "othervalue": "othervalue" -} diff --git a/Examples/Transformer_looptests.json b/Examples/Transformer_looptests.json deleted file mode 100644 index f69e6ef..0000000 --- a/Examples/Transformer_looptests.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "iPhoneNumbers1": { - "#loop($.people[*].phoneNumbers[?(@.type=='iPhone')])": { - "phoneNumber": "#concat(#currentvalueatpath($.countryPrefix), #currentvalueatpath($.number))" - } - }, - "iPhoneNumbers2": { - "#loop($.people[?(@.name=='Jim' || @.name=='John')].phoneNumbers[?(@.type=='iPhone')])": { - "phoneNumber": "#concat(#currentvalueatpath($.countryPrefix), #currentvalueatpath($.number))" - } - }, - "iPhoneNumbers3": { - "#loop($.people[?(@.name=='Jim1' || @.name=='John')].phoneNumbers[?(@.type=='iPhone')])": { - "phoneNumber": "#concat(#currentvalueatpath($.countryPrefix), #currentvalueatpath($.number))" - } - }, - "iPhoneNumbers4": { - "#loop($.people[?(@.name=='Jim1' || @.name=='John1')].phoneNumbers[?(@.type=='iPhone')])": { - "phoneNumber": "#concat(#currentvalueatpath($.countryPrefix), #currentvalueatpath($.number))" - } - }, - "iPhoneNumbers5": { - "#loop($.people[*].phoneNumbers[?(@.type== '#valueof($.PhoneTypeToSearch)')])": { - "phoneNumber": "#concat(#currentvalueatpath($.countryPrefix), #currentvalueatpath($.number))" - } - } -} \ No newline at end of file diff --git a/Examples/Transformer_nestedfunctions.json b/Examples/Transformer_nestedfunctions.json deleted file mode 100644 index d9accf0..0000000 --- a/Examples/Transformer_nestedfunctions.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "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),:)))" - } -} diff --git a/Examples/Transformer_nestedloop.json b/Examples/Transformer_nestedloop.json deleted file mode 100644 index 99efe80..0000000 --- a/Examples/Transformer_nestedloop.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "hello": { - "#loop($.NestedLoop.Organization.Employee)": { - "CurrentName": "#currentvalueatpath($.Name)", - "Details": { - "#loopwithincontext($.Details)": { - "CurrentCountry": "#currentvalueatpath($.Country)" - } - } - } - } -} \ No newline at end of file diff --git a/Examples/Transformer_replace.json b/Examples/Transformer_replace.json deleted file mode 100644 index 3e1ff0a..0000000 --- a/Examples/Transformer_replace.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "#": [ "#copy($)", "#replace($.menu.id,#valueof($.menu.value))" ] -} \ No newline at end of file diff --git a/Examples/Transformer_string.json b/Examples/Transformer_string.json deleted file mode 100644 index adf1e1f..0000000 --- a/Examples/Transformer_string.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "stringresult": { - "lastindexofand": "#lastindexof(#valueof($.stringref),and)", - "firstindexofand": "#firstindexof(#valueof($.stringref),and)", - "subsrting": "#substring(#valueof($.stringref),8,10)", - "concat": "#concat(#valueof($.menu.id.file),#valueof($.menu.value.Window))" - } -} diff --git a/Examples/Transformer_valueof.json b/Examples/Transformer_valueof.json deleted file mode 100644 index 828c74c..0000000 --- a/Examples/Transformer_valueof.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "root": { - "menu1": "#valueof($.menu.popup.menuitem[?(@.value=='New')].onclick)", - "menu2": "#valueof($.menu.popup.menuitem[?(@.value=='Open')].onclick)" - }, - -} \ No newline at end of file diff --git a/Examples/Transformer_valueofarray.json b/Examples/Transformer_valueofarray.json deleted file mode 100644 index 96c907a..0000000 --- a/Examples/Transformer_valueofarray.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "root": { - "array": { - - "fullarray": "#valueof($.x)", - "arrayelement": "#valueof($.x[0])", - "specificelement": "#valueof($.x[1].v.a)" - } - } - -} diff --git a/Examples/Transformer_xfunctions.json b/Examples/Transformer_xfunctions.json deleted file mode 100644 index 8f4e940..0000000 --- a/Examples/Transformer_xfunctions.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "FullName": "#xconcat(#valueof($.Name),#constant_comma(),#valueof($.MiddleName),#constant_comma(),#valueof($.Surname))", - "AgeOfParents": "#xadd(#valueof($.AgeOfMother),#valueof($.AgeOfFather))" -} \ No newline at end of file diff --git a/Examples/ValidationInput.json b/Examples/ValidationInput.json deleted file mode 100644 index 4daa776..0000000 --- a/Examples/ValidationInput.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "x.tree": { "x.branch": { "x.leaf": "1" } }, - "x.child": "1", - "y.animal": "1" -} diff --git a/ExternalMethods/ExternalClass.cs b/ExternalMethods/ExternalClass.cs deleted file mode 100644 index 986ee6f..0000000 --- a/ExternalMethods/ExternalClass.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Newtonsoft.Json.Linq; -using System; - -namespace ExternalMethods -{ - public class ExternalClass - { - public static string StaticMethod() - { - return "External Static"; - } - - public string InstanceMethod() - { - return "External Instance"; - } - - public string StaticTypedParameters(int n, bool b, string s, DateTime d) - { - return "External Static TypedParameters success"; - } - - public string TypedParameters(int n, bool b, string s, DateTime d) - { - return "External TypedParameters success"; - } - - public string NavigateTypedParameters(bool val) - { - return val.ToString(); - } - } -} diff --git a/ExternalMethods/ExternalMethods.csproj b/ExternalMethods/ExternalMethods.csproj deleted file mode 100644 index 7977d1b..0000000 --- a/ExternalMethods/ExternalMethods.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - netstandard2.0 - - - - - - - diff --git a/ExternalMethods/Season.cs b/ExternalMethods/Season.cs deleted file mode 100644 index 28e35cb..0000000 --- a/ExternalMethods/Season.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -namespace SeasonsHelper -{ - public class Season - { - public static bool IsSummer(bool hot, int averageDaysOfRain, DateTime randomDay) - { - return hot && averageDaysOfRain < 20 && randomDay > new DateTime(2018, 6, 21); - } - } -} diff --git a/InternalClass.cs b/InternalClass.cs deleted file mode 100644 index a8cfb3c..0000000 --- a/InternalClass.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Newtonsoft.Json.Linq; -using System; - -namespace InternalMethods -{ - public class InternalClass - { - public static string StaticMethod() - { - return "Internal Static"; - } - - public string InstanceMethod() - { - return "Internal Instance"; - } - - public string StaticTypedParameters(int n, bool b, string s, DateTime d) - { - return "Internal Static TypedParameters success"; - } - - public string TypedParameters(int n, bool b, string s, DateTime d) - { - return "Internal TypedParameters success"; - } - - public string NavigateTypedParameters(JObject token) - { - return token.ToString(); - } - } -} diff --git a/JUST.NET.Test.csproj b/JUST.NET.Test.csproj deleted file mode 100644 index 5712e2c..0000000 --- a/JUST.NET.Test.csproj +++ /dev/null @@ -1,195 +0,0 @@ - - - - - Debug - AnyCPU - {507F2FFD-22BD-433E-9CEC-0B210DF18ED3} - Exe - Properties - JUST.NET.Test - JUST.NET.Test - v4.6.1 - 512 - true - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll - - - packages\Newtonsoft.Json.Schema.3.0.10\lib\net45\Newtonsoft.Json.Schema.dll - - - - - - - - - - - - - - - - - - - - Designer - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Always - - - Designer - - - - - Always - - - - - {15f60fac-38cf-4aa7-b369-e738702aa94e} - ExternalMethods - - - {c33053bc-a3f2-4f0a-9b7f-b0af5ad4effb} - JUST.net - - - - - \ No newline at end of file diff --git a/JUST.NET.Test.sln b/JUST.NET.sln similarity index 55% rename from JUST.NET.Test.sln rename to JUST.NET.sln index 21b84ea..e3bf876 100644 --- a/JUST.NET.Test.sln +++ b/JUST.NET.sln @@ -1,13 +1,17 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26730.10 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30413.136 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JUST.NET.Test", "JUST.NET.Test.csproj", "{507F2FFD-22BD-433E-9CEC-0B210DF18ED3}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JUST.net", "JUST.net\JUST.net.csproj", "{C33053BC-A3F2-4F0A-9B7F-B0AF5AD4EFFB}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExternalMethods", "ExternalMethods\ExternalMethods.csproj", "{15F60FAC-38CF-4AA7-B369-E738702AA94E}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ENV", "ENV", "{FF566713-3F06-4A89-9127-1916A9DB3C3E}" + ProjectSection(SolutionItems) = preProject + azure-pipelines.yml = azure-pipelines.yml + README.md = README.md + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JUST.Net.Test", "JUST.Net.Test\JUST.Net.Test.csproj", "{4D2D7084-412B-4782-A687-BA2C22D3D14B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -15,18 +19,14 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {507F2FFD-22BD-433E-9CEC-0B210DF18ED3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {507F2FFD-22BD-433E-9CEC-0B210DF18ED3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {507F2FFD-22BD-433E-9CEC-0B210DF18ED3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {507F2FFD-22BD-433E-9CEC-0B210DF18ED3}.Release|Any CPU.Build.0 = Release|Any CPU {C33053BC-A3F2-4F0A-9B7F-B0AF5AD4EFFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C33053BC-A3F2-4F0A-9B7F-B0AF5AD4EFFB}.Debug|Any CPU.Build.0 = Debug|Any CPU {C33053BC-A3F2-4F0A-9B7F-B0AF5AD4EFFB}.Release|Any CPU.ActiveCfg = Release|Any CPU {C33053BC-A3F2-4F0A-9B7F-B0AF5AD4EFFB}.Release|Any CPU.Build.0 = Release|Any CPU - {15F60FAC-38CF-4AA7-B369-E738702AA94E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {15F60FAC-38CF-4AA7-B369-E738702AA94E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {15F60FAC-38CF-4AA7-B369-E738702AA94E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {15F60FAC-38CF-4AA7-B369-E738702AA94E}.Release|Any CPU.Build.0 = Release|Any CPU + {4D2D7084-412B-4782-A687-BA2C22D3D14B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D2D7084-412B-4782-A687-BA2C22D3D14B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D2D7084-412B-4782-A687-BA2C22D3D14B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4D2D7084-412B-4782-A687-BA2C22D3D14B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JUST.Net.Test/DynamicExpressionDateTimeTest.cs b/JUST.Net.Test/DynamicExpressionDateTimeTest.cs new file mode 100644 index 0000000..a652c02 --- /dev/null +++ b/JUST.Net.Test/DynamicExpressionDateTimeTest.cs @@ -0,0 +1,39 @@ +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Text; +using Xunit; + +namespace JUST.Net.Test +{ + public class DynamicExpressionDateTimeTest + { + [Fact] + public void DateTime_Test() + { + var input = @"{ }"; + var transformer = @"{ ""dt"": ""~(DateTime.Now.Date)"" }"; + + var jsonTransformer = new JsonTransformer(); + var result = jsonTransformer.Transform(transformer, input); + + var obj = JObject.Parse(result); + Assert.Equal(DateTime.Now.Date, obj.SelectToken("$.dt").Value()); + Assert.True(true); + } + + [Fact] + public void DateTime_Format_Test() + { + var input = @"{ }"; + var transformer = @"{ ""dt"": ""~(DateTime.Now.ToString(\""ddMMyyyy\""))"" }"; + + var jsonTransformer = new JsonTransformer(); + var result = jsonTransformer.Transform(transformer, input); + + var obj = JObject.Parse(result); + Assert.Equal(DateTime.Now.ToString("ddMMyyyy"), obj.SelectToken("$.dt").Value()); + Assert.True(true); + } + } +} diff --git a/JUST.Net.Test/DynamicExpressionRegexTest.cs b/JUST.Net.Test/DynamicExpressionRegexTest.cs new file mode 100644 index 0000000..da663be --- /dev/null +++ b/JUST.Net.Test/DynamicExpressionRegexTest.cs @@ -0,0 +1,37 @@ +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Text; +using Xunit; + +namespace JUST.Net.Test +{ + public class DynamicExpressionRegexTest + { + [Fact] + public void SimpleNumber_Test() + { + var input = @"{ }"; + var transformer = @"{ ""rg"": ""~(regex(\""V-12345\"", \""@@\\d+\"", \""0\""))"" }"; + + var jsonTransformer = new JsonTransformer(); + var result = jsonTransformer.Transform(transformer, input); + + var obj = JObject.Parse(result); + Assert.Equal("12345", obj.SelectToken("$.rg").Value()); + } + + [Fact] + public void SimpleNumber_Test_Defaukt() + { + var input = @"{ }"; + var transformer = @"{ ""rg"": ""~(regex(\""VHHG\"", \""d+\"", \""111\""))"" }"; + + var jsonTransformer = new JsonTransformer(); + var result = jsonTransformer.Transform(transformer, input); + + var obj = JObject.Parse(result); + Assert.Equal("111", obj.SelectToken("$.rg").Value()); + } + } +} diff --git a/JUST.Net.Test/DynamicExpressoArrayTest.cs b/JUST.Net.Test/DynamicExpressoArrayTest.cs new file mode 100644 index 0000000..5acb470 --- /dev/null +++ b/JUST.Net.Test/DynamicExpressoArrayTest.cs @@ -0,0 +1,33 @@ +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Text; +using Xunit; + +namespace JUST.Net.Test +{ + public class DynamicExpressoArrayTest + { + [Fact] + public void Array_ValueOf_Object_Test() + { + var input = @"{ ""array"": [ { ""name"": ""hans"" }, { ""name"": ""simplic"" } ] }"; + + var transformer = @"{ ""ar"": { ""#loop($.array)"": { ""n"": ""~(valueOfIterStr(\""$.name\""))"", ""index"": ""~(currentIndex)"", ""last"": ""~(lastIndex)"" } } }"; + + var jsonTransformer = new JsonTransformer(); + var result = jsonTransformer.Transform(transformer, input); + + var obj = JObject.Parse(result); + Assert.Equal("hans", obj.SelectToken("$.ar[0].n").Value()); + Assert.Equal("simplic", obj.SelectToken("$.ar[1].n").Value()); + + Assert.Equal(0, obj.SelectToken("$.ar[0].index").Value()); + Assert.Equal(1, obj.SelectToken("$.ar[1].index").Value()); + + Assert.Equal(1, obj.SelectToken("$.ar[0].last").Value()); + Assert.Equal(1, obj.SelectToken("$.ar[1].last").Value()); + Assert.True(true); + } + } +} diff --git a/JUST.Net.Test/DynamicExpressoTest.cs b/JUST.Net.Test/DynamicExpressoTest.cs new file mode 100644 index 0000000..93e6ffb --- /dev/null +++ b/JUST.Net.Test/DynamicExpressoTest.cs @@ -0,0 +1,69 @@ +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Text; +using Xunit; + +namespace JUST.Net.Test +{ + public class DynamicExpressoTest + { + [Fact] + public void StringConcat_Static_Test() + { + var input = @"{ ""firstName"": ""max"", ""lastName"": ""foo"" }"; + //var transformer = @"{ ""friendlyName"": ""~(valueOf(c, \""$.firstName\"") + valueOf(c, \""$.lastName\""))"" }"; + var transformer = @"{ ""friendlyName"": ""~(\""max\"" + \"" \"" + \""foo\"")"" }"; + + var jsonTransformer = new JsonTransformer(); + var result = jsonTransformer.Transform(transformer, input); + + var obj = JObject.Parse(result); + Assert.Equal("max foo", obj.SelectToken("$.friendlyName").Value()); + Assert.True(true); + } + + [Fact] + public void String_ValueOf_Test() + { + var input = @"{ ""firstName"": ""max"" }"; + //var transformer = @"{ ""friendlyName"": ""~(valueOf(c, \""$.firstName\"") + valueOf(c, \""$.lastName\""))"" }"; + var transformer = @"{ ""friendlyName"": ""~(valueOf(\""$.firstName\""))"" }"; + + var jsonTransformer = new JsonTransformer(); + var result = jsonTransformer.Transform(transformer, input); + + var obj = JObject.Parse(result); + Assert.Equal("max", obj.SelectToken("$.friendlyName").Value()); + Assert.True(true); + } + + [Fact] + public void String_ValueOf_Concat_Test() + { + var input = @"{ ""firstName"": ""max"", ""lastName"": ""foo"" }"; + var transformer = @"{ ""friendlyName"": ""~(valueOfStr(\""$.firstName\"") + valueOfStr(\""$.lastName\""))"" }"; + + var jsonTransformer = new JsonTransformer(); + var result = jsonTransformer.Transform(transformer, input); + + var obj = JObject.Parse(result); + Assert.Equal("maxfoo", obj.SelectToken("$.friendlyName").Value()); + Assert.True(true); + } + + [Fact] + public void String_ValueOf_Add_Test() + { + var input = @"{ ""val1"": 1, ""val2"": ""3"" }"; + var transformer = @"{ ""val"": ""~(valueOfInt(\""$.val1\"") + valueOfInt(\""$.val2\""))"" }"; + + var jsonTransformer = new JsonTransformer(); + var result = jsonTransformer.Transform(transformer, input); + + var obj = JObject.Parse(result); + Assert.Equal("4", obj.SelectToken("$.val").Value()); + Assert.True(true); + } + } +} diff --git a/JUST.Net.Test/ExpressionParserTest.cs b/JUST.Net.Test/ExpressionParserTest.cs new file mode 100644 index 0000000..612c6ab --- /dev/null +++ b/JUST.Net.Test/ExpressionParserTest.cs @@ -0,0 +1,44 @@ +using JUST.net; +using Xunit; + +namespace JUST.Net.Test +{ + public class ExpressionParserTest + { + [Fact] + public void ExpressionTest_False() + { + var isExpression = ExpressionParserUtilities.IsExpression("~Sample Value", out string expression); + + Assert.False(isExpression); + Assert.Equal("", expression); + } + + [Fact] + public void ExpressionTest_NoNested_False() + { + var isExpression = ExpressionParserUtilities.IsExpression("~Sample ~(some-not-expression) Value", out string expression); + + Assert.False(isExpression); + Assert.Equal("", expression); + } + + [Fact] + public void ExpressionTest_True() + { + var isExpression = ExpressionParserUtilities.IsExpression("~(func(\"Sample Value\"))", out string expression); + + Assert.True(isExpression); + Assert.Equal("func(\"Sample Value\")", expression); + } + + [Fact] + public void ExpressionTest_EmptyExpression_True() + { + var isExpression = ExpressionParserUtilities.IsExpression("~()", out string expression); + + Assert.True(isExpression); + Assert.Equal("", expression); + } + } +} diff --git a/JUST.Net.Test/JUST.Net.Test.csproj b/JUST.Net.Test/JUST.Net.Test.csproj new file mode 100644 index 0000000..0a14dc5 --- /dev/null +++ b/JUST.Net.Test/JUST.Net.Test.csproj @@ -0,0 +1,20 @@ + + + + net6.0 + + false + + + + + + + + + + + + + + diff --git a/JUST.Net.Test/PathNotExistsTest.cs b/JUST.Net.Test/PathNotExistsTest.cs new file mode 100644 index 0000000..acc81bb --- /dev/null +++ b/JUST.Net.Test/PathNotExistsTest.cs @@ -0,0 +1,84 @@ +using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Text; +using Xunit; + +namespace JUST.Net.Test +{ + public class PathNotExistsTest + { + [Fact] + public void PathNotExists_Test_Str() + { + var input = @"{ }"; + + var transformer = @"{ ""val"": ""~(valueOfStr(\""$.test.test.test\""))"" }"; + + var jsonTransformer = new JsonTransformer(); + var result = jsonTransformer.Transform(transformer, input); + + var obj = JObject.Parse(result); + Assert.Equal("", obj.SelectToken("$.val").Value()); + Assert.True(true); + } + + [Fact] + public void PathNotExists_Test_Int() + { + var input = @"{ }"; + + var transformer = @"{ ""val"": ""~(valueOfInt(\""$.test.test.test\""))"" }"; + + var jsonTransformer = new JsonTransformer(); + var result = jsonTransformer.Transform(transformer, input); + + var obj = JObject.Parse(result); + Assert.Equal(0, obj.SelectToken("$.val").Value()); + Assert.True(true); + } + + [Fact] + public void PathNotExists_Test_Double() + { + var input = @"{ }"; + + var transformer = @"{ ""val"": ""~(valueOfDouble(\""$.test.test.test\""))"" }"; + + var jsonTransformer = new JsonTransformer(); + var result = jsonTransformer.Transform(transformer, input); + + var obj = JObject.Parse(result); + Assert.Equal(0.0, obj.SelectToken("$.val").Value()); + Assert.True(true); + } + + [Fact] + public void PathNotExists_Test_Str_Exception() + { + var input = @"{ }"; + + var transformer = @"{ ""val"": ""~(valueOfStr(\""$.test.test.test\""))"" }"; + + var jsonTransformer = new JsonTransformer + { + StrictPathHandling = true + }; + + var exceptionCaused = false; + + try + { + jsonTransformer.Transform(transformer, input); + } + catch (PathNotFoundException ex) + { + exceptionCaused = true; + Assert.Contains("$.test.test.test", ex.Message); + } + + Assert.True(exceptionCaused); + } + } +} diff --git a/JUST.net/DataTransformer.cs b/JUST.net/DataTransformer.cs deleted file mode 100644 index 60c2522..0000000 --- a/JUST.net/DataTransformer.cs +++ /dev/null @@ -1,356 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; - -namespace JUST -{ - public class DataTransformer - { - private static string Parse(string transformer, string inputJson, JArray array, JToken currentArrayElement) - { - int startIndex = 0, index = 0; - - while ((startIndex < transformer.Length) && (index = transformer.IndexOf('#', startIndex)) != -1) - { - string functionString = GetFunctionString(transformer, index); - - - if (functionString != null) - { - if (functionString.Contains("loop")) - { - string loopArgsInclusive = GetLoopArguments(index, transformer, true); - string loopArgs = GetLoopArguments(index, transformer, false); - - string evaluatedFunction = (string)EvaluateFunction(functionString, inputJson, array, currentArrayElement, loopArgs); - - - StringBuilder builder = new StringBuilder(transformer); - builder.Remove(index-1, loopArgsInclusive.Length+1); - builder.Insert(index-1, evaluatedFunction); - transformer = builder.ToString(); - - startIndex = index + evaluatedFunction.Length; - - } - else - { - - string evaluatedFunction = (string)EvaluateFunction(functionString, inputJson, array, currentArrayElement, null); - - if (!string.IsNullOrEmpty(evaluatedFunction)) - { - - StringBuilder builder = new StringBuilder(transformer); - builder.Remove(index, functionString.Length); - builder.Insert(index, evaluatedFunction); - transformer = builder.ToString(); - - startIndex = index + evaluatedFunction.Length; - } - } - } - else - break; - } - - return transformer; - } - - public static string Transform(string transformer, string inputJson) - { - - return Parse(transformer, inputJson,null,null); - - } - - private static string GetLoopArguments(int startIdex, string input,bool inclusive) - { - string loopArgs = string.Empty; - - - int openBrackettCount = 0; - int closebrackettCount = 0; - - - int bStartIndex = 0; - int bEndIndex = 0; - for (int i = startIdex; i < input.Length; i++) - { - char currentChar = input[i]; - - if (currentChar == '{') - { - if (openBrackettCount == 0) - bStartIndex = i; - - openBrackettCount++; - } - - if (currentChar == '}') - { - bEndIndex = i; - closebrackettCount++; - } - - - - if (openBrackettCount > 0 && openBrackettCount == closebrackettCount) - { - if(!inclusive) - loopArgs = input.Substring(bStartIndex, bEndIndex - bStartIndex + 1); - else - loopArgs = input.Substring(startIdex, bEndIndex - startIdex + 1); - break; - } - - } - - if (inclusive && loopArgs == string.Empty) - return "#loop"; - - return loopArgs; - } - - private static string EvaluateFunction(string functionString, string inputJson, JArray array, JToken currentArrayElement, - string loopArgumentString) - { - string output = null; - - functionString = functionString.Trim().Substring(1); - - int indexOfStart = functionString.IndexOf("("); - - if (indexOfStart != -1) - { - - string functionName = functionString.Substring(0, indexOfStart); - - string argumentString = functionString.Substring(indexOfStart + 1, functionString.Length - indexOfStart - 2); - - string[] arguments = GetArguments(argumentString); - - string[] parameters = new string[arguments.Length + 1]; - - int i = 0; - if (arguments != null && arguments.Length > 0) - { - foreach (string argument in arguments) - { - string trimmedArgument = argument; - - if (argument.Contains("#")) - trimmedArgument = argument.Trim(); - - if (trimmedArgument.StartsWith("#")) - { - parameters[i] = (string)EvaluateFunction(trimmedArgument, inputJson, array, currentArrayElement, loopArgumentString); - } - else - parameters[i] = trimmedArgument; - i++; - } - - } - - parameters[i] = inputJson; - - if (functionName == "loop") - { - output = GetLoopResult(parameters, loopArgumentString); - } - else if (functionName == "currentvalue" || functionName == "currentindex" || functionName == "lastindex" - || functionName == "lastvalue") - output = (string)caller("JUST.Transformer", functionName, new object[] { array, currentArrayElement }); - else if (functionName == "currentvalueatpath" || functionName == "lastvalueatpath") - output = (string)caller("JUST.Transformer", functionName, new object[] { array, currentArrayElement, arguments[0] }); - else if (functionName == "customfunction") - output = (string)CallCustomFunction(parameters); - else if (functionName == "xconcat" || functionName == "xadd" || functionName == "mathequals" || functionName == "mathgreaterthan" || functionName == "mathlessthan" - || functionName == "mathgreaterthanorequalto" - || functionName == "mathlessthanorequalto" || functionName == "stringcontains" || - functionName == "stringequals") - { - object[] oParams = new object[1]; - oParams[0] = parameters; - output = caller("JUST.Transformer", functionName, oParams).ToString(); - } - else - output = caller("JUST.Transformer", functionName, parameters).ToString(); - } - return output; - } - - - private static string GetLoopResult(string[] parameters,string loopArgumentString) - { - string returnString = string.Empty; - - if (parameters.Length < 2) - throw new Exception("Incorrect number of parameters for function #Loop"); - - string input = parameters[1]; - - if (parameters.Length == 3) - input = parameters[2]; - - JsonReader reader = new JsonTextReader(new StringReader(input)); - reader.DateParseHandling = DateParseHandling.None; - JToken token = JObject.Load(reader); - - JToken selectedToken = token.SelectToken(parameters[0]); - - if (selectedToken.Type != JTokenType.Array) - throw new Exception("The JSONPath argument inside a #loop function must be an Array"); - - JArray selectedArr = selectedToken as JArray; - - string seperator = Environment.NewLine; - - if (parameters.Length == 3) - seperator = parameters[1]; - - foreach (JToken arrToken in selectedToken.Children()) - { - string parsedrecord = Parse(loopArgumentString, input, selectedArr, arrToken); - - returnString += parsedrecord.Substring(1, parsedrecord.Length - 2); - returnString += seperator; - } - - return returnString; - } - - private static string GetFunctionString(string input, int startIndex) - { - string functionString = string.Empty; - - int brackettOpenCount = 0; - int brackettClosedCount = 0; - - for(int i = startIndex; i < input.Length; i++) - { - char c = input[i]; - - if (c == '(') - brackettOpenCount++; - if (c == ')') - brackettClosedCount++; - - if( brackettClosedCount > 0 && brackettClosedCount == brackettOpenCount) - { - functionString = input.Substring(startIndex, i - startIndex + 1); - break; - } - } - - return functionString; - } - - private static object CallCustomFunction(object[] parameters) - { - object[] customParameters = new object[parameters.Length - 3]; - string functionString = string.Empty; - string dllName = string.Empty; - int i = 0; - foreach (object parameter in parameters) - { - if (i == 0) - dllName = parameter.ToString(); - else if (i == 1) - functionString = parameter.ToString(); - else - if (i != (parameters.Length - 1)) - customParameters[i - 2] = parameter; - - i++; - } - - int index = functionString.LastIndexOf("."); - - string className = functionString.Substring(0, index); - string functionName = functionString.Substring(index + 1, functionString.Length - index - 1); - - className = className + "," + dllName; - - return caller(className, functionName, customParameters); - - } - - private static object caller(String myclass, String mymethod, object[] parameters) - { - Assembly assembly = Assembly.GetEntryAssembly(); - - Type type = Type.GetType(myclass); - // Create an instance of that type - //Object obj = Activator.CreateInstance(type); - // Retrieve the method you are looking for - MethodInfo methodInfo = type.GetTypeInfo().GetMethod(mymethod); - // Invoke the method on the instance we created above - return methodInfo.Invoke(null, parameters); - } - - - - private static string[] GetArguments(string argumentString) - { - bool brackettOpen = false; - - List arguments = null; - int index = 0; - - int openBrackettCount = 0; - int closebrackettCount = 0; - - for (int i = 0; i < argumentString.Length; i++) - { - char currentChar = argumentString[i]; - - if (currentChar == '(') - openBrackettCount++; - - if (currentChar == ')') - closebrackettCount++; - - if (openBrackettCount == closebrackettCount) - brackettOpen = false; - else - brackettOpen = true; - - if ((currentChar == ',') && (!brackettOpen)) - { - if (arguments == null) - arguments = new List(); - - if (index != 0) - arguments.Add(argumentString.Substring(index + 1, i - index - 1)); - else - arguments.Add(argumentString.Substring(index, i)); - index = i; - } - - } - - if (index > 0) - { - arguments.Add(argumentString.Substring(index + 1, argumentString.Length - index - 1)); - } - else - { - if (arguments == null) - arguments = new List(); - arguments.Add(argumentString); - } - - return arguments.ToArray(); - } - - - } -} diff --git a/JUST.net/Exception/ExpressionException.cs b/JUST.net/Exception/ExpressionException.cs new file mode 100644 index 0000000..f08982e --- /dev/null +++ b/JUST.net/Exception/ExpressionException.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; + +namespace JUST +{ + public class ExpressionException : Exception + { + public ExpressionException() + { + } + + public ExpressionException(string message) : base(message) + { + } + + public ExpressionException(string message, Exception innerException) : base(message, innerException) + { + } + + protected ExpressionException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + } +} diff --git a/JUST.net/Exception/PathNotFoundException.cs b/JUST.net/Exception/PathNotFoundException.cs new file mode 100644 index 0000000..0c59627 --- /dev/null +++ b/JUST.net/Exception/PathNotFoundException.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Text; + +namespace JUST +{ + public class PathNotFoundException : Exception + { + public PathNotFoundException() + { + } + + public PathNotFoundException(string message) : base(message) + { + } + + public PathNotFoundException(string message, Exception innerException) : base(message, innerException) + { + } + + protected PathNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + } +} diff --git a/JUST.net/ExpressionInterpreter.cs b/JUST.net/ExpressionInterpreter.cs new file mode 100644 index 0000000..18e4b37 --- /dev/null +++ b/JUST.net/ExpressionInterpreter.cs @@ -0,0 +1,133 @@ +using DynamicExpresso; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace JUST.net +{ + /// + /// JUST expresso interprter implementation + /// + internal class ExpressionInterpreter : Interpreter + { + private bool strictPathHandling; + + /// + /// Initialize interpreter + /// + public ExpressionInterpreter() + { + // Add references + Reference(typeof(DateTime)); + Reference(typeof(String)); + Reference(typeof(Convert)); + Reference(typeof(Regex)); + } + + /// + /// Initialize core methods + /// + public void Setup(JToken inputObject, bool strictPathHandling) + + { + this.strictPathHandling = strictPathHandling; + + Func valueOfStr = (path) => Transformer.ValueOf(path, inputObject, strictPathHandling, "").ToString(); + Func valueOf = (path) => Transformer.ValueOf(path, inputObject, strictPathHandling, new object()); + Func valueOfInt = (path) => + { + int.TryParse(Transformer.ValueOf(path, inputObject, strictPathHandling, 0)?.ToString(), out int r); + return r; + }; + Func valueOfDouble = (path) => + { + double.TryParse(Transformer.ValueOf(path, inputObject, strictPathHandling, 0)?.ToString(), out double r); + return r; + }; + Func nullToString = (value) => value ?? ""; + + Func regex = (value, pattern, defaultValue) => + { + var result = Regex.Match(value, pattern); + if (result.Success) + return result.Value; + + return defaultValue; + }; + + Func createSplitList = (value, separator) => + { + if (value == null) + return new JArray(); + + if (separator == null) + throw new Exception("createSplitList two paramters (value, separator)"); + + var splits = value.Split(new string[] { separator }, StringSplitOptions.RemoveEmptyEntries); + return JArray.FromObject(splits); + }; + + SetFunction("valueOf", valueOf); + SetFunction("valueOfStr", valueOfStr); + SetFunction("valueOfInt", valueOfInt); + SetFunction("valueOfDouble", valueOfDouble); + SetFunction("nullToString", nullToString); + SetFunction("createSplitList", createSplitList); + SetFunction("regex", regex); + } + + /// + /// Initialize core methods + /// + public void SetContext(JToken arrayElement, JArray array, string expression) + { + Func valueOfStr = (path) => Transformer.ValueOf(path, arrayElement, strictPathHandling, "").ToString(); + Func valueOf = (path) => Transformer.ValueOf(path, arrayElement, strictPathHandling, new object()); + Func valueOfInt = (path) => + { + int.TryParse(Transformer.ValueOf(path, arrayElement, strictPathHandling, 0)?.ToString(), out int r); + return r; + }; + Func valueOfDouble = (path) => + { + double.TryParse(Transformer.ValueOf(path, arrayElement, strictPathHandling, 0)?.ToString(), out double r); + return r; + }; + + SetFunction("valueOfIter", valueOf); + SetFunction("valueOfIterStr", valueOfStr); + SetFunction("valueOfIterInt", valueOfInt); + SetFunction("valueOfIterDouble", valueOfDouble); + + var identifiers = DetectIdentifiers(expression); + if (identifiers != null) + { + + foreach (var identifier in identifiers.UnknownIdentifiers.Concat(identifiers.Identifiers.Select(x => x.Name))) + { + switch (identifier) + { + case "currentIndex": + SetVariable("currentIndex", array.IndexOf(arrayElement)); + break; + + case "lastIndex": + SetVariable("lastIndex", array.IndexOf(array.Last)); + break; + + case "arrayElementStr": + { + if (arrayElement == null) + SetVariable("currentElementStr", arrayElement.ToString()); + SetVariable("currentElementStr", arrayElement.ToString()); + } + break; + } + } + } + } + } +} diff --git a/JUST.net/ExpressionParserUtilities.cs b/JUST.net/ExpressionParserUtilities.cs new file mode 100644 index 0000000..738ad8a --- /dev/null +++ b/JUST.net/ExpressionParserUtilities.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JUST.net +{ + /// + /// Expression utilities + /// + public static class ExpressionParserUtilities + { + /// + /// Checks whether a string represents an expression + /// + /// Json string value + /// If value is an expression, the expression string will be returned as this output parameter + /// True if the input string is an expression + public static bool IsExpression(string value, out string expression) + { + expression = ""; + + if (string.IsNullOrWhiteSpace(value)) + return false; + + var trimmedValue = value.Trim(); + if (trimmedValue.StartsWith("~(") && trimmedValue.EndsWith(")")) + { + expression = trimmedValue.Substring(2, trimmedValue.Length - 3); + return true; + } + + return false; + } + } +} diff --git a/JUST.net/JUST.net.csproj b/JUST.net/JUST.net.csproj index dd0f448..85fc1bf 100644 --- a/JUST.net/JUST.net.csproj +++ b/JUST.net/JUST.net.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 @@ -9,16 +9,28 @@ This will repace the JUST and JUST.NETCore packages. https://github.com/WorkMaze/JUST.net/blob/master/License.md C#;.NET;JSON;XSLT;Transformation;Schema https://github.com/WorkMaze/JUST.net - true + false true Fixed the following issues:- https://github.com/WorkMaze/JUST.net/issues/26 https://github.com/WorkMaze/JUST.net/issues/25 + 6.0.24.905 + 6.0.24.905 + 6.0.24 + + + + bin\Release + + + + bin\Debug - - + + + diff --git a/JUST.net/JsonTransformer.cs b/JUST.net/JsonTransformer.cs index 1639d42..6e4724e 100644 --- a/JUST.net/JsonTransformer.cs +++ b/JUST.net/JsonTransformer.cs @@ -1,4 +1,5 @@ -using Newtonsoft.Json; +using JUST.net; +using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; @@ -10,10 +11,33 @@ namespace JUST { public class JsonTransformer { - public static string Transform(string transformerJson, string inputJson) + #region Fields + private const string DefaultTransformerNamespace = "JUST.Transformer"; + private readonly ExpressionInterpreter expressionInterpreter; + private JToken inputObject; + #endregion + + #region Constructor + /// + /// Initialize json transformer + /// + public JsonTransformer() + { + expressionInterpreter = new ExpressionInterpreter(); + } + #endregion + + #region [Transform] + /// + /// Transform json by json as string + /// + /// Transformer as .net string + /// Input as .net string (json) + /// + public string Transform(string transformerJson, string inputJson) { - JToken result = null; JToken transformerToken = JToken.Parse(transformerJson); + JToken result; switch (transformerToken.Type) { case JTokenType.Object: @@ -26,12 +50,18 @@ public static string Transform(string transformerJson, string inputJson) throw new NotSupportedException($"Transformer of type '{transformerToken.Type}' not supported!"); } - string output = JsonConvert.SerializeObject(result); + string output = JsonConvert.SerializeObject(result, Formatting.Indented); return output; } - public static JArray Transform(JArray transformerArray, string input) + /// + /// Transform json array (JArray) + /// + /// Transformer as array + /// Input as .net string (json) + /// Transformed json + public JArray Transform(JArray transformerArray, string input) { var result = new JArray(); foreach (var transformer in transformerArray) @@ -46,21 +76,39 @@ public static JArray Transform(JArray transformerArray, string input) return result; } - public static JObject Transform(JObject transformer, JObject input) + /// + /// Transform JObject by using a JObject transformer + /// + /// Transformer as NewtonsoftJson object + /// Input as Newtonsoft.Json object + /// Transformed json as JObject + public JObject Transform(JObject transformer, JObject input) { string inputJson = JsonConvert.SerializeObject(input); return Transform(transformer, inputJson); } - public static JObject Transform(JObject transformer, string input) + /// + /// Transform json by using a JObject + /// + /// Transformer as JObject + /// Json to transform + /// Transformed JObject + public JObject Transform(JObject transformer, string input) { + JsonReader reader = new JsonTextReader(new StringReader(input)); + reader.DateParseHandling = DateParseHandling.None; + inputObject = JObject.Load(reader); + + expressionInterpreter.Setup(inputObject, StrictPathHandling); + RecursiveEvaluate(transformer, input, null, null); return transformer; } - #region RecursiveEvaluate - + #endregion - private static void RecursiveEvaluate(JToken parentToken, string inputJson, JArray parentArray, JToken currentArrayToken) + #region RecursiveEvaluate + private void RecursiveEvaluate(JToken parentToken, string inputJson, JArray parentArray, JToken currentArrayToken) { if (parentToken == null) return; @@ -80,9 +128,6 @@ private static void RecursiveEvaluate(JToken parentToken, string inputJson, JArr foreach (JToken childToken in tokens) { - - - if (childToken.Type == JTokenType.Array && (parentToken as JProperty).Name.Trim() != "#") { JArray arrayToken = childToken as JArray; @@ -149,37 +194,67 @@ private static void RecursiveEvaluate(JToken parentToken, string inputJson, JArr if (tokensToDelete == null) tokensToDelete = new List(); - tokensToDelete.Add(Delete(arrayValue.Value())); - - } } - } - if (property.Name != null && property.Value.ToString().Trim().StartsWith("#") - && !property.Name.Contains("#eval") && !property.Name.Contains("#ifgroup") - && !property.Name.Contains("#loop")) + if (ExpressionParserUtilities.IsExpression(property.Value.ToString().Trim(), out string expression)) { - object newValue = ParseFunction(property.Value.ToString(), inputJson, parentArray, currentArrayToken); + expressionInterpreter.SetContext(currentArrayToken, parentArray, expression); - if (newValue != null && newValue.ToString().Contains("\"")) + try { - try + expression = expression.Replace("@@\\", @"\\"); + + var result = expressionInterpreter.Eval(expression); + + if (result is JArray arrayValue) { - JToken newToken = JToken.Parse(newValue.ToString()); - property.Value = newToken; + property.Value = arrayValue; + continue; // Skip further processing } - catch + if (result is JObject jObject) { - property.Value = new JValue(newValue); + property.Value = jObject; + continue; // Skip further processing } + else + property.Value = new JValue(result); + } + catch (PathNotFoundException ex) + { + throw; + } + catch (Exception ex) + { + throw new Exception($"Could not execute expression: {expression}. Property: {property}.", ex); } - else - property.Value = new JValue(newValue); } + // TODO: Not required anymore + // if (property.Name != null && property.Value.ToString().Trim().StartsWith("#") + // && !property.Name.Contains("#eval") && !property.Name.Contains("#ifgroup") + // && !property.Name.Contains("#loop")) + // { + // object newValue = ParseFunction(property.Value.ToString(), inputJson, parentArray, currentArrayToken); + // + // if (newValue != null && newValue.ToString().Contains("\"")) + // { + // try + // { + // JToken newToken = JToken.Parse(newValue.ToString()); + // property.Value = newToken; + // } + // catch + // { + // property.Value = new JValue(newValue); + // } + // } + // else + // property.Value = new JValue(newValue); + // } + /* For looping*/ isLoop = false; @@ -201,13 +276,11 @@ private static void RecursiveEvaluate(JToken parentToken, string inputJson, JArr if (tokensToAdd == null) { - tokensToAdd = new List(); - - tokensToAdd.Add(clonedProperty); + tokensToAdd = new List + { + clonedProperty + }; } - - - } if (property.Name != null && property.Name.Contains("#ifgroup")) @@ -216,20 +289,45 @@ private static void RecursiveEvaluate(JToken parentToken, string inputJson, JArr int endIndex = property.Name.LastIndexOf(")"); string functionString = property.Name.Substring(startIndex + 1, endIndex - startIndex - 1); - - object functionResult = ParseFunction(functionString, inputJson, null, null); bool result = false; - try + if (ExpressionParserUtilities.IsExpression(functionString, out string exp)) { - result = Convert.ToBoolean(functionResult); + try + { + exp = exp.Replace("@@\\", @"\\"); + + try + { + result = (bool)expressionInterpreter.Eval(exp); + } + catch (Exception ex) + { + throw new Exception("#ifgroup expression can only handle boolean data types. E.g. ~(1 == 1)", ex); + } + } + catch (PathNotFoundException ex) + { + throw; + } + catch (Exception ex) + { + throw new Exception($"Could not execute expression: {expression}. Property: {property}.", ex); + } } - catch + else { - result = false; - } - + object functionResult = ParseFunction(functionString, inputJson, null, null); + try + { + result = Convert.ToBoolean(functionResult); + } + catch + { + result = false; + } + } if (result == true) { @@ -242,7 +340,7 @@ private static void RecursiveEvaluate(JToken parentToken, string inputJson, JArr if (tokenToForm == null) { - tokenToForm = new List(); + tokenToForm = new List(); } foreach (JToken grandChildToken in childToken.Children()) @@ -256,10 +354,6 @@ private static void RecursiveEvaluate(JToken parentToken, string inputJson, JArr loopProperties.Add(property.Name); } - - - - isLoop = true; } @@ -278,38 +372,46 @@ private static void RecursiveEvaluate(JToken parentToken, string inputJson, JArr reader.DateParseHandling = DateParseHandling.None; JToken token = JObject.Load(reader); JToken arrayToken = null; - if (strArrayToken.Contains("#")) + + if (strArrayToken.Contains("#") && !strArrayToken.Trim().StartsWith("#")) { int sIndex = strArrayToken.IndexOf("#"); string sub1 = strArrayToken.Substring(0, sIndex); - int indexOfENdFubction = GetIndexOfFunctionEnd(strArrayToken); + int indexOfEndFunction = GetIndexOfFunctionEnd(strArrayToken); - if (indexOfENdFubction > sIndex && sIndex > 0) + if (indexOfEndFunction > sIndex && sIndex > 0) { - string sub2 = strArrayToken.Substring(indexOfENdFubction + 1, strArrayToken.Length - indexOfENdFubction - 1); + string sub2 = strArrayToken.Substring(indexOfEndFunction + 1, strArrayToken.Length - indexOfEndFunction - 1); - string functionResult = ParseFunction(strArrayToken.Substring(sIndex, indexOfENdFubction - sIndex + 1), inputJson, parentArray, currentArrayToken).ToString(); + string functionResult = ParseFunction(strArrayToken.Substring(sIndex, indexOfEndFunction - sIndex + 1), inputJson, parentArray, currentArrayToken).ToString(); strArrayToken = sub1 + functionResult + sub2; } } - try - { - arrayToken = token.SelectToken(strArrayToken); - if (arrayToken is JObject) - { - arrayToken = new JArray(arrayToken); - } - } - catch + if (strArrayToken.Trim().StartsWith("#")) { - var multipleTokens = token.SelectTokens(strArrayToken); + arrayToken = ParseFunction(strArrayToken, inputJson, parentArray, currentArrayToken) as JArray; + } - arrayToken = new JArray(multipleTokens); + if (arrayToken == null) + { + try + { + arrayToken = token.SelectToken(strArrayToken); + if (arrayToken is JObject) + { + arrayToken = new JArray(arrayToken); + } + } + catch + { + var multipleTokens = token.SelectTokens(strArrayToken); + arrayToken = new JArray(multipleTokens); + } } if (arrayToken == null) @@ -351,11 +453,9 @@ private static void RecursiveEvaluate(JToken parentToken, string inputJson, JArr /*End looping */ } - if (childToken.Type == JTokenType.String && childToken.Value().Trim().StartsWith("#") + if (childToken.Type == JTokenType.String && childToken.Value().Trim().StartsWith("#") && parentArray != null && currentArrayToken != null) { - - object newValue = ParseFunction(childToken.Value(), inputJson, parentArray, currentArrayToken); if (newValue != null && newValue.ToString().Contains("\"")) @@ -367,7 +467,7 @@ private static void RecursiveEvaluate(JToken parentToken, string inputJson, JArr } catch { - + } } else @@ -473,7 +573,7 @@ private static void RecursiveEvaluate(JToken parentToken, string inputJson, JArr #endregion #region Copy - private static JToken Copy(string inputString, string inputJson) + private JToken Copy(string inputString, string inputJson) { int indexOfStart = inputString.IndexOf("(", 0); int indexOfEnd = inputString.LastIndexOf(")"); @@ -492,7 +592,7 @@ private static JToken Copy(string inputString, string inputJson) #endregion #region Delete - private static string Delete(string inputString) + private string Delete(string inputString) { int indexOfStart = inputString.IndexOf("(", 0); int indexOfEnd = inputString.LastIndexOf(")"); @@ -508,7 +608,7 @@ private static string Delete(string inputString) #endregion #region Replace - private static JToken Replace(string inputString, string inputJson) + private JToken Replace(string inputString, string inputJson) { int indexOfStart = inputString.IndexOf("(", 0); int indexOfEnd = inputString.LastIndexOf(")"); @@ -534,7 +634,7 @@ private static JToken Replace(string inputString, string inputJson) } - private static string GetTokenStringToReplace(string inputString) + private string GetTokenStringToReplace(string inputString) { int indexOfStart = inputString.IndexOf("(", 0); int indexOfEnd = inputString.LastIndexOf(")"); @@ -553,7 +653,7 @@ private static string GetTokenStringToReplace(string inputString) #region ParseFunction - private static object ParseFunction(string functionString, string inputJson, JArray array, JToken currentArrayElement) + private object ParseFunction(string functionString, string inputJson, JArray array, JToken currentArrayElement) { try { @@ -581,6 +681,7 @@ private static object ParseFunction(string functionString, string inputJson, JAr { string trimmedArgument = argument; + // Missing contains here! if (argument.Contains("#")) trimmedArgument = argument.Trim(); @@ -597,34 +698,64 @@ private static object ParseFunction(string functionString, string inputJson, JAr parameters[i] = inputJson; - if (functionName == "currentvalue" || functionName == "currentindex" || functionName == "lastindex" - || functionName == "lastvalue") - output = ReflectionHelper.caller(null, "JUST.Transformer", functionName, new object[] { array, currentArrayElement }); - else if (functionName == "currentvalueatpath" || functionName == "lastvalueatpath") - output = ReflectionHelper.caller(null, "JUST.Transformer", functionName, new object[] { array, currentArrayElement, arguments[0] }); - else if (functionName == "customfunction") - output = CallCustomFunction(parameters); - else if (Regex.IsMatch(functionName, ReflectionHelper.EXTERNAL_ASSEMBLY_REGEX)){ - output = ReflectionHelper.CallExternalAssembly(functionName, parameters); - } - else if (functionName == "xconcat" || functionName == "xadd" - || functionName == "mathequals" || functionName == "mathgreaterthan" || functionName == "mathlessthan" - || functionName == "mathgreaterthanorequalto" - || functionName == "mathlessthanorequalto" || functionName == "stringcontains" || - functionName == "stringequals") + if (functionName == "getroot") + output = inputJson; + else if (functionName == "getparent") { - object[] oParams = new object[1]; - oParams[0] = parameters; - output = ReflectionHelper.caller(null, "JUST.Transformer", functionName, oParams); + if (currentArrayElement == null) + throw new Exception("getparent is only allowed inside loop."); + + output = currentArrayElement.Parent.ToString(); } - else + else if (functionName == "createarray") { - if (currentArrayElement != null && functionName != "valueof") + var newArray = new JArray(); + + var arrayCount = int.Parse(parameters[0].ToString()); + var arrayItemName = parameters[1].ToString(); + var makeArrayValueParameters = parameters.Skip(2).ToList(); + + for (int elementId = 0; elementId < arrayCount; elementId++) { - parameters[i] = JsonConvert.SerializeObject(currentArrayElement); + var arrayItem = new JObject(); + + string lastParameterName = null; + for (int parameterId = 0; parameterId < makeArrayValueParameters.Count; parameterId++) + { + if (parameterId % 2 == 0) + lastParameterName = makeArrayValueParameters[parameterId].ToString(); + if (parameterId % 2 != 0) + { + arrayItem.Add(new JProperty(lastParameterName, makeArrayValueParameters[parameterId])); + + lastParameterName = ""; + } + } + + if (lastParameterName != "") + arrayItem.Add(new JProperty(lastParameterName, null)); + + newArray.Add(arrayItem); } - output = ReflectionHelper.caller(null, "JUST.Transformer", functionName, parameters); + + output = newArray; } + // TODO: Remove + ///else if (functionName == "currentvalue" || functionName == "currentindex" || functionName == "lastindex" + /// || functionName == "lastvalue") + /// output = ReflectionHelper.InvokeFunction(null, "JUST.Transformer", functionName, new object[] { array, currentArrayElement }); + ///else if (functionName == "currentvalueatpath" || functionName == "lastvalueatpath") + /// output = ReflectionHelper.InvokeFunction(null, "JUST.Transformer", functionName, new object[] { array, currentArrayElement, arguments[0] }); + ///else if (functionName == "customfunction") + /// output = CallCustomFunction(parameters); + ///else + ///{ + /// if (currentArrayElement != null && functionName != "valueof") + /// { + /// parameters[i] = JsonConvert.SerializeObject(currentArrayElement); + /// } + /// output = ReflectionHelper.InvokeFunction(null, DefaultTransformerNamespace, functionName, parameters); + ///} return output; } @@ -633,41 +764,14 @@ private static object ParseFunction(string functionString, string inputJson, JAr throw new Exception("Error while calling function : " + functionString + " - " + ex.Message, ex); } } - - private static object CallCustomFunction(object[] parameters) - { - object[] customParameters = new object[parameters.Length - 3]; - string functionString = string.Empty; - string dllName = string.Empty; - int i = 0; - foreach (object parameter in parameters) - { - if (i == 0) - dllName = parameter.ToString(); - else if (i == 1) - functionString = parameter.ToString(); - else - if (i != (parameters.Length - 1)) - customParameters[i - 2] = parameter; - - i++; - } - - int index = functionString.LastIndexOf("."); - - string className = functionString.Substring(0, index); - string functionName = functionString.Substring(index + 1, functionString.Length - index - 1); - - className = className + "," + dllName; - - return ReflectionHelper.caller(null, className, functionName, customParameters); - - } #endregion #region GetArguments - private static string[] GetArguments(string functionString) + private string[] GetArguments(string rawArgument) { + if (rawArgument.Trim() == "") + return new string[] { }; + bool brackettOpen = false; List arguments = null; @@ -675,16 +779,24 @@ private static string[] GetArguments(string functionString) int openBrackettCount = 0; int closebrackettCount = 0; - - for (int i = 0; i < functionString.Length; i++) + for (int i = 0; i < rawArgument.Length; i++) { - char currentChar = functionString[i]; + string currentArgument; + if (index != 0) + currentArgument = rawArgument.Substring(index + 1, i - index - 1); + else + currentArgument = rawArgument.Substring(index, i); - if (currentChar == '(') - openBrackettCount++; + char currentChar = rawArgument[i]; - if (currentChar == ')') - closebrackettCount++; + if (currentArgument.Trim().StartsWith("#")) + { + if (currentChar == '(') + openBrackettCount++; + + if (currentChar == ')') + closebrackettCount++; + } if (openBrackettCount == closebrackettCount) brackettOpen = false; @@ -696,10 +808,8 @@ private static string[] GetArguments(string functionString) if (arguments == null) arguments = new List(); - if (index != 0) - arguments.Add(functionString.Substring(index + 1, i - index - 1)); - else - arguments.Add(functionString.Substring(index, i)); + arguments.Add(currentArgument); + index = i; } @@ -707,79 +817,20 @@ private static string[] GetArguments(string functionString) if (index > 0) { - arguments.Add(functionString.Substring(index + 1, functionString.Length - index - 1)); + arguments.Add(rawArgument.Substring(index + 1, rawArgument.Length - index - 1)); } else { if (arguments == null) arguments = new List(); - arguments.Add(functionString); + arguments.Add(rawArgument); } return arguments.ToArray(); } #endregion - #region Split - public static IEnumerable SplitJson(string input, string arrayPath) - { - JObject inputJObject = JObject.Parse(input); - - List jObjects = SplitJson(inputJObject, arrayPath).ToList(); - - List output = null; - - foreach (JObject jObject in jObjects) - { - if (output == null) - output = new List(); - - output.Add(JsonConvert.SerializeObject(jObject)); - } - - return output; - } - - public static IEnumerable SplitJson(JObject input, string arrayPath) - { - List jsonObjects = null; - - JToken tokenArr = input.SelectToken(arrayPath); - - string pathToReplace = tokenArr.Path; - - if (tokenArr != null && tokenArr is JArray) - { - JArray array = tokenArr as JArray; - - foreach (JToken tokenInd in array) - { - - string path = tokenInd.Path; - - JToken clonedToken = input.DeepClone(); - - JToken foundToken = clonedToken.SelectToken("$." + path); - JToken tokenToReplcae = clonedToken.SelectToken("$." + pathToReplace); - - tokenToReplcae.Replace(foundToken); - - if (jsonObjects == null) - jsonObjects = new List(); - - jsonObjects.Add(clonedToken as JObject); - - - } - } - else - throw new Exception("ArrayPath must be a valid JSON path to a JSON array."); - - return jsonObjects; - } - #endregion - - private static int GetIndexOfFunctionEnd(string totalString) + private int GetIndexOfFunctionEnd(string totalString) { int index = -1; @@ -804,5 +855,11 @@ private static int GetIndexOfFunctionEnd(string totalString) return index; } + + /// + /// Gets or sets whether to use strict path handling. If set to true, an exception will be caused + /// if a path is not existing. + /// + public bool StrictPathHandling { get; set; } = false; } } diff --git a/JUST.net/JsonUtilities.cs b/JUST.net/JsonUtilities.cs new file mode 100644 index 0000000..6e110ff --- /dev/null +++ b/JUST.net/JsonUtilities.cs @@ -0,0 +1,68 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace JUST.net +{ + public static class JsonUtilities + { + public static IEnumerable SplitJson(string input, string arrayPath) + { + JObject inputJObject = JObject.Parse(input); + + List jObjects = SplitJson(inputJObject, arrayPath).ToList(); + + List output = null; + + foreach (JObject jObject in jObjects) + { + if (output == null) + output = new List(); + + output.Add(JsonConvert.SerializeObject(jObject)); + } + + return output; + } + + public static IEnumerable SplitJson(JObject input, string arrayPath) + { + List jsonObjects = null; + + JToken tokenArr = input.SelectToken(arrayPath); + + string pathToReplace = tokenArr.Path; + + if (tokenArr != null && tokenArr is JArray) + { + JArray array = tokenArr as JArray; + + foreach (JToken tokenInd in array) + { + + string path = tokenInd.Path; + + JToken clonedToken = input.DeepClone(); + + JToken foundToken = clonedToken.SelectToken("$." + path); + JToken tokenToReplcae = clonedToken.SelectToken("$." + pathToReplace); + + tokenToReplcae.Replace(foundToken); + + if (jsonObjects == null) + jsonObjects = new List(); + + jsonObjects.Add(clonedToken as JObject); + + + } + } + else + throw new Exception("ArrayPath must be a valid JSON path to a JSON array."); + + return jsonObjects; + } + } +} diff --git a/JUST.net/JsonValidator.cs b/JUST.net/JsonValidator.cs index e09f7a6..d62a2b8 100644 --- a/JUST.net/JsonValidator.cs +++ b/JUST.net/JsonValidator.cs @@ -116,9 +116,7 @@ private static void PrefixKey(JObject jo, string prefix) private static void HandleEvent(object sender, SchemaValidationEventArgs args) { - throw new Exception( args.Message); - + throw new Exception( args.Message); } - } } diff --git a/JUST.net/Parser.cs b/JUST.net/Parser.cs deleted file mode 100644 index 711c4f5..0000000 --- a/JUST.net/Parser.cs +++ /dev/null @@ -1,195 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace JUST -{ - public class LoopContents - { - public string Evaluated { get; set; } - - public int Start { get; set; } - - public int End { get; set; } - } - - public class Parser - { - - public static string Parse(string input, string loop) - { - int startIndex = 0, index = 0; - - while ((index = input.IndexOf('#', startIndex)) != -1) - { - int endElementIndex = input.IndexOf('"', index); - int startingElementIndex = input.LastIndexOf('"', startIndex); - - - if (endElementIndex > index) - { - startIndex = endElementIndex + 1; - string functionString = input.Substring(index, endElementIndex - index); - - - if (functionString.Trim().Contains("#loop")) - { - LoopContents content = FindLoopContents(input, endElementIndex, functionString); - Console.WriteLine(content.Evaluated); - - StringBuilder builder = new StringBuilder(input); - builder.Remove(content.Start, content.End - content.Start + 1); - builder.Insert(content.Start, content.Evaluated); - input = builder.ToString(); - - startIndex = content.Start + content.Evaluated.Length;// content.End; - -                        //StringBuilder builder = new StringBuilder(input); -                        //builder.Remove(startingElementIndex, content.End - startingElementIndex); -                        //builder.Insert(startingElementIndex, "[" + content.Evaluated + "]"); -                        //input = builder.ToString(); - -                        //startIndex = startingElementIndex + content.Evaluated.Length + 2; -                    } - else - { - StringBuilder builder = new StringBuilder(input); - builder.Remove(index, endElementIndex - index); - string evaluatedFunction = EvaluateFunction(functionString, loop); - builder.Insert(index, evaluatedFunction); - input = builder.ToString(); - - startIndex = index + evaluatedFunction.Length; - } - -                    //Console.WriteLine(functionString); -                } - else - break; - } - - return input; - - - } - - public static string EvaluateFunction(string functionString, string loop) - { - return loop == null ? "SAY_WHAT" : loop + "_YES"; - } - - public static LoopContents FindLoopContents(string input, int startIndex, string loop) - { - - LoopContents contents = new LoopContents(); - - string remainingString = input.Substring(startIndex); - - string result = string.Empty; - - int indexOfColon = remainingString.IndexOf(':'); - - - char searchCharacter = '{'; - bool searchCharaterInitialized = false; - - int opened = 0; - int closed = 0; - - - if (indexOfColon != -1) - { - - remainingString = remainingString.Substring(indexOfColon + 1); - - int startCharIndex = indexOfColon; - - int endCharIndex = indexOfColon; - - int i = 0; - foreach (char c in remainingString) - { - if (c == '"') - { - if (!searchCharaterInitialized) - { - searchCharaterInitialized = true; - searchCharacter = '"'; - startCharIndex = i; - opened++; - } - else - { - if (searchCharaterInitialized && (searchCharacter == '"')) - closed++; - endCharIndex = i; - } - } - if (c == '[') - { - if (!searchCharaterInitialized) - { - searchCharaterInitialized = true; - searchCharacter = '['; - startCharIndex = i; - } - if (searchCharacter == '[') - opened++; - } - if (c == '{') - { - if (!searchCharaterInitialized) - { - searchCharaterInitialized = true; - searchCharacter = '{'; - startCharIndex = i; - } - if (searchCharacter == '{') - opened++; - } - if (c == ']') - { - if (searchCharaterInitialized && (searchCharacter == '[')) - { - closed++; - endCharIndex = i; - } - } - if (c == '}') - { - if (searchCharaterInitialized && (searchCharacter == '{')) - { - closed++; - endCharIndex = i; - } - } - - if (closed > 0 && closed >= opened) - break; - - i++; - } - - result = remainingString.Substring(startCharIndex, endCharIndex - startCharIndex + 1); - - contents.Start = startIndex + startCharIndex + indexOfColon + 1; - contents.End = startIndex + endCharIndex + indexOfColon + 1; - } - - contents.Evaluated = result; - - if (contents.Start == 0) - contents.Start = startIndex + 1; - if (contents.End == 0) - contents.End = startIndex + 1; - - contents.Evaluated = Parse(contents.Evaluated, loop); - - return contents; - } - - - } -} \ No newline at end of file diff --git a/JUST.net/Properties/PublishProfiles/FolderProfile.pubxml b/JUST.net/Properties/PublishProfiles/FolderProfile.pubxml index 5672e42..cef52a6 100644 --- a/JUST.net/Properties/PublishProfiles/FolderProfile.pubxml +++ b/JUST.net/Properties/PublishProfiles/FolderProfile.pubxml @@ -1,13 +1,13 @@  FileSystem - Release - netstandard1.6 - bin\Release\PublishOutput + Debug + netstandard2.0 + bin\Debug\PublishOutput + Any CPU \ No newline at end of file diff --git a/JUST.net/ReflectionHelper.cs b/JUST.net/ReflectionHelper.cs deleted file mode 100644 index 9dfbf81..0000000 --- a/JUST.net/ReflectionHelper.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text.RegularExpressions; - -namespace JUST -{ - internal class ReflectionHelper - { - internal const string EXTERNAL_ASSEMBLY_REGEX = "([\\w.]+)[:]{2}([\\w.]+)[:]{0,2}([\\w.]*)"; - - internal static object caller(Assembly assembly, String myclass, String mymethod, object[] parameters, bool convertParameters = false) - { - Type type = assembly?.GetType(myclass) ?? Type.GetType(myclass); - MethodInfo methodInfo = type.GetTypeInfo().GetMethod(mymethod); - var instance = !methodInfo.IsStatic ? Activator.CreateInstance(type) : null; - - var typedParameters = new List(); - if (convertParameters) - { - var parameterInfos = methodInfo.GetParameters(); - for (int i = 0; i < parameterInfos.Length; i++) - { - var pType = parameterInfos[i].ParameterType; - typedParameters.Add(GetTypedValue(pType, parameters[i])); - } - } - return methodInfo.Invoke(instance, convertParameters ? typedParameters.ToArray() : parameters); - } - - internal static object CallExternalAssembly(string functionName, object[] parameters) - { - var match = Regex.Match(functionName, EXTERNAL_ASSEMBLY_REGEX); - var isAssemblyDefined = match.Groups.Count == 4 && match.Groups[3].Value != string.Empty; - var assemblyName = isAssemblyDefined ? match.Groups[1].Value : null; - var namespc = match.Groups[isAssemblyDefined ? 2 : 1].Value; - var methodName = match.Groups[isAssemblyDefined ? 3 : 2].Value; - - var assembly = GetAssembly(isAssemblyDefined, assemblyName, namespc, methodName); - if (assembly != null) - { - return caller(assembly, namespc, methodName, FilterParameters(parameters), true); - } - - throw new MissingMethodException((assemblyName != null ? $"{assemblyName}." : string.Empty) + $"{namespc}.{methodName}"); - } - - private static Assembly GetAssembly(bool isAssemblyDefined, string assemblyName, string namespc, string methodName) - { - var assemblies = AppDomain.CurrentDomain.GetAssemblies(); - if (isAssemblyDefined) - { - var assemblyFileName = !assemblyName.EndsWith(".dll") ? $"{assemblyName}.dll" : assemblyName; - var assembly = assemblies.SingleOrDefault(a => a.ManifestModule.Name == assemblyFileName); - if (assembly == null) - { - var assemblyLocation = Path.Combine(Directory.GetCurrentDirectory(), assemblyFileName); - assembly = Assembly.LoadFile(assemblyLocation); - AppDomain.CurrentDomain.Load(assembly.GetName()); - } - - return assembly; - } - else - { - foreach (var assembly in assemblies.Where(a => !a.FullName.StartsWith("System."))) - { - Type[] types = null; - try - { - types = assembly.GetTypes(); - } - catch (ReflectionTypeLoadException ex) - { - types = ex.Types; - } - - foreach (var typeInfo in types) - { - if (string.Compare(typeInfo.FullName, namespc, StringComparison.InvariantCultureIgnoreCase) == 0) - { - return assembly; - } - } - } - } - return null; - } - - private static object[] FilterParameters(object[] parameters) - { - if (string.IsNullOrEmpty(parameters[0]?.ToString() ?? string.Empty)) - { - parameters = parameters.Skip(1).ToArray(); - } - if (parameters.Length > 0 && parameters.Last().ToString() == "{}") - { - parameters = parameters.Take(parameters.Length - 1).ToArray(); - } - return parameters; - } - - private static object GetTypedValue(Type pType, object val) - { - object typedValue = val; - var converter = TypeDescriptor.GetConverter(pType); - if (converter.CanConvertFrom(val.GetType())) - { - typedValue = converter.ConvertFrom(val); - } - else if (pType.IsPrimitive) - { - typedValue = Convert.ChangeType(val, pType); - } - else if (!pType.IsAbstract) - { - var parse = pType.GetMethod("Parse", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(string) }, null); - typedValue = parse?.Invoke(null, new[] { val }) ?? pType.GetConstructor(new[] { typeof(string) })?.Invoke(new[] { val }) ?? val; - } - return typedValue; - } - } -} diff --git a/JUST.net/Transformer.cs b/JUST.net/Transformer.cs index 69dcffa..c92e038 100644 --- a/JUST.net/Transformer.cs +++ b/JUST.net/Transformer.cs @@ -1,27 +1,45 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using System.Globalization; using System.IO; namespace JUST { - internal class Transformer + internal static class Transformer { - public static object valueof(string jsonPath, string inputJson) + public static object ValueOf(string jsonPath, JToken input, bool strictPathHandling, object defaultValue) { - JsonReader reader = new JsonTextReader(new StringReader(inputJson)); - reader.DateParseHandling = DateParseHandling.None; - JToken token = JObject.Load(reader); - //JToken token = JObject.Parse(inputJson); + JToken selectedToken = input.SelectToken(jsonPath); - JToken selectedToken = token.SelectToken(jsonPath); - return GetValue(selectedToken); + if (strictPathHandling) + { + if (selectedToken == null) + { + throw new PathNotFoundException($"Could not find object at path: {jsonPath},"); + } + } + + return GetValue(selectedToken, defaultValue); } + public static object getarray(string document, string jsonPath, string inputJson) + { + JsonReader reader = new JsonTextReader(new StringReader(document)) + { + DateParseHandling = DateParseHandling.None + }; + JToken token = JObject.Load(reader); + + var jsonArrayToken = token.SelectTokens(jsonPath).ToList(); + var array = new JArray(); + foreach (var arrayToken in jsonArrayToken) + array.Add(arrayToken); + + var arrayAsString = array.ToString(); + + return arrayAsString; + } public static string exists(string jsonPath, string inputJson) { @@ -68,24 +86,6 @@ public static object ifcondition(object condition, object value, object trueResu #region string functions - public static string concat(string string1, string string2, string inputJson) - { - string string2Result = (string2 != null) ? string2 : string.Empty; - return string1 != null ? string1 + string2Result : string.Empty + string2Result; - } - - public static string substring(string stringRef, string startIndex, string length, string inputJson) - { - try - { - return stringRef.Substring(Convert.ToInt32(startIndex), Convert.ToInt32(length)); - } - catch - { - return null; - } - } - public static string firstindexof(string stringRef, string searchString, string inputJson) { return stringRef.IndexOf(searchString, 0).ToString(); @@ -96,18 +96,28 @@ public static string lastindexof(string stringRef, string searchString, string i return stringRef.LastIndexOf(searchString).ToString(); } - public static string concatall(string array, string inputJson) + public static string listall(string array, string separator, string inputJson) { string result = null; - JArray parsedArray = JArray.Parse(array); + JArray parsedArray = Utilities.ParseOrGetEmpty(array); if (parsedArray != null) { + var isFirstItem = true; + foreach (JToken token in parsedArray.Children()) { if (result == null) result = string.Empty; + + if (!isFirstItem && !string.IsNullOrWhiteSpace(result)) + { + result += separator; + } + + isFirstItem = false; + result += token.ToString(); } } @@ -115,66 +125,56 @@ public static string concatall(string array, string inputJson) return result; } - public static string concatallatpath(string array, string jsonPath, string inputJson) + public static string listallatpath(string array, string jsonPath, string separator, string inputJson) { string result = null; - JArray parsedArray = JArray.Parse(array); + JArray parsedArray = Utilities.ParseOrGetEmpty(array); if (parsedArray != null) { - + var isFirstItem = true; foreach (JToken token in parsedArray.Children()) { - JToken selectedToken = token.SelectToken(jsonPath); + if (selectedToken == null) + continue; + if (result == null) result = string.Empty; + if (!isFirstItem && !string.IsNullOrWhiteSpace(result)) + { + result += separator; + } + + isFirstItem = false; + result += selectedToken.ToString(); } } return result; } - #endregion - #region math functions - - - public static string add(string num1, string num2, string inputJson) + #region aggregate functions + public static object count(string array, string inputJson) { try { - return (Convert.ToInt32(num1) + Convert.ToInt32(num2)).ToString(); + JArray parsedArray = Utilities.ParseOrGetEmpty(array); + return parsedArray.Count; } catch { return null; } } - public static string subtract(string num1, string num2, string inputJson) - { - try { return (Convert.ToInt32(num1) - Convert.ToInt32(num2)).ToString(); } - catch { return null; } - } - public static string multiply(string num1, string num2, string inputJson) - { - try { return (Convert.ToInt32(num1) * Convert.ToInt32(num2)).ToString(); } - catch { return null; } - } - public static string divide(string num1, string num2, string inputJson) - { - try { return (Convert.ToInt32(num1) / Convert.ToInt32(num2)).ToString(); } - catch { return null; } - } - #endregion - #region aggregate functions public static string sum(string array, string inputJson) { try { - JArray parsedArray = JArray.Parse(array); + JArray parsedArray = Utilities.ParseOrGetEmpty(array); double integerresult = 0; @@ -198,7 +198,7 @@ public static string sumatpath(string array, string jsonPath, string inputJson) { double integerresult = 0; - JArray parsedArray = JArray.Parse(array); + JArray parsedArray = Utilities.ParseOrGetEmpty(array); if (parsedArray != null) { @@ -218,11 +218,35 @@ public static string sumatpath(string array, string jsonPath, string inputJson) catch { return null; } } + public static string firstatpath(string array, string jsonPath, string inputJson) + { + try + { + JArray parsedArray = Utilities.ParseOrGetEmpty(array); + + if (parsedArray != null) + { + + foreach (JToken token in parsedArray.Children()) + { + + JToken selectedToken = token.SelectToken(jsonPath); + + if (selectedToken != null) + return selectedToken?.ToString(); + } + } + + return null; + } + catch { return null; } + } + public static string average(string array, string inputJson) { try { - JArray parsedArray = JArray.Parse(array); + JArray parsedArray = Utilities.ParseOrGetEmpty(array); double integerresult = 0; @@ -246,7 +270,7 @@ public static string averageatpath(string array, string jsonPath, string inputJs { double integerresult = 0; - JArray parsedArray = JArray.Parse(array); + JArray parsedArray = Utilities.ParseOrGetEmpty(array); if (parsedArray != null) { @@ -270,7 +294,7 @@ public static string max(string array, string inputJson) { try { - JArray parsedArray = JArray.Parse(array); + JArray parsedArray = Utilities.ParseOrGetEmpty(array); double integerresult = 0; int i = 0; @@ -305,7 +329,7 @@ public static string maxatpath(string array, string jsonPath, string inputJson) double integerresult = 0; int i = 0; - JArray parsedArray = JArray.Parse(array); + JArray parsedArray = Utilities.ParseOrGetEmpty(array); if (parsedArray != null) { @@ -332,7 +356,10 @@ public static string maxatpath(string array, string jsonPath, string inputJson) return integerresult.ToString(); } - catch { return null; } + catch + { + return null; + } } @@ -340,7 +367,7 @@ public static string min(string array, string inputJson) { try { - JArray parsedArray = JArray.Parse(array); + JArray parsedArray = Utilities.ParseOrGetEmpty(array); double integerresult = 0; int i = 0; @@ -375,7 +402,7 @@ public static string minatpath(string array, string jsonPath, string inputJson) double integerresult = 0; int i = 0; - JArray parsedArray = JArray.Parse(array); + JArray parsedArray = Utilities.ParseOrGetEmpty(array); if (parsedArray != null) { @@ -409,7 +436,7 @@ public static string arraylength(string array, string inputJson) { try { - JArray parsedArray = JArray.Parse(array); + JArray parsedArray = Utilities.ParseOrGetEmpty(array); return parsedArray.Count.ToString(); @@ -419,99 +446,15 @@ public static string arraylength(string array, string inputJson) #endregion - #region arraylooping - public static object currentvalue(JArray array, JToken currentElement) - { - - return GetValue(currentElement); - } - - public static string currentindex(JArray array, JToken currentElement) + public static object GetValue(JToken selectedToken, object defaultValue) { - return array.IndexOf(currentElement).ToString(); - } - - - public static object lastvalue(JArray array, JToken currentElement) - { - - return GetValue(array.Last); - } - - public static string lastindex(JArray array, JToken currentElement) - { - return (array.Count - 1).ToString(); - } - - public static object currentvalueatpath(JArray array, JToken currentElement, string jsonPath) - { - JToken selectedToken = currentElement.SelectToken(jsonPath); - - return GetValue(selectedToken); - } - - public static object lastvalueatpath(JArray array, JToken currentElement, string jsonPath) - { - - JToken selectedToken = array.Last.SelectToken(jsonPath); - - return GetValue(selectedToken); - } - #endregion - - #region Constants - - public static string constant_comma(string none, string inputJson) - { - return ","; - } - - public static string constant_hash(string none, string inputJson) - { - return "#"; - } - - #endregion - - #region Variable parameter functions - public static string xconcat(object[] list) - { - string result = string.Empty; - - for (int i = 0; i < list.Length - 1; i++) - { - if (list[i] != null) - result += list[i].ToString(); - } - - return result; - } - - public static string xadd(object[] list) - { - int add = 0; - - for (int i = 0; i < list.Length - 1; i++) - { - if (list[i] != null) - add += Convert.ToInt32(list[i]); - } - - return add.ToString(); - } - #endregion - - public static object GetValue(JToken selectedToken) - { - object output = null; + object output = defaultValue; if (selectedToken != null) { - if (selectedToken.Type == JTokenType.Date) { DateTime value = Convert.ToDateTime(selectedToken.Value()); - output = value.ToString("yyyy-MM-ddTHH:mm:sszzzz"); } else @@ -567,119 +510,5 @@ public static object grouparrayby(string jsonPath, string groupingElement, strin } #endregion - - #region operators - public static string stringequals(object[] list) - { - bool result = false; - - if (list.Length >= 2) - { - if (list[0].ToString().Equals(list[1].ToString())) - result = true; - } - - return result.ToString(); - } - - public static string stringcontains(object[] list) - { - bool result = false; - - if (list.Length >= 2) - { - if (list[0].ToString().Contains(list[1].ToString())) - result = true; - } - - return result.ToString(); - } - - public static string mathequals(object[] list) - { - bool result = false; - - - if (list.Length >= 2) - { - decimal lshDecimal = Convert.ToDecimal(list[0]); - decimal rhsDecimal = Convert.ToDecimal(list[1]); - - if (lshDecimal == rhsDecimal) - result = true; - } - - return result.ToString(); - } - - public static string mathgreaterthan(object[] list) - { - bool result = false; - - - if (list.Length >= 2) - { - decimal lshDecimal = Convert.ToDecimal(list[0]); - decimal rhsDecimal = Convert.ToDecimal(list[1]); - - if (lshDecimal > rhsDecimal) - result = true; - } - - return result.ToString(); - } - - public static string mathlessthan(object[] list) - { - bool result = false; - - - if (list.Length >= 2) - { - decimal lshDecimal = Convert.ToDecimal(list[0]); - decimal rhsDecimal = Convert.ToDecimal(list[1]); - - if (lshDecimal < rhsDecimal) - result = true; - } - - return result.ToString(); - } - - public static string mathgreaterthanorequalto(object[] list) - { - bool result = false; - - - if (list.Length >= 2) - { - decimal lshDecimal = Convert.ToDecimal(list[0]); - decimal rhsDecimal = Convert.ToDecimal(list[1]); - - if (lshDecimal >= rhsDecimal) - result = true; - } - - return result.ToString(); - } - - public static string mathlessthanorequalto(object[] list) - { - bool result = false; - - - if (list.Length >= 2) - { - decimal lshDecimal = Convert.ToDecimal(list[0]); - decimal rhsDecimal = Convert.ToDecimal(list[1]); - - if (lshDecimal <= rhsDecimal) - result = true; - } - - return result.ToString(); - } - #endregion - } } diff --git a/JUST.net/Utilities.cs b/JUST.net/Utilities.cs index 5139007..d9c8d83 100644 --- a/JUST.net/Utilities.cs +++ b/JUST.net/Utilities.cs @@ -8,44 +8,12 @@ namespace JUST { public class Utilities { - public static IDictionary FlattenJson(string inputJson) + public static JArray ParseOrGetEmpty(string arrayTokens) { - JToken parent = JToken.Parse(inputJson); + if (string.IsNullOrWhiteSpace(arrayTokens)) + arrayTokens = "[]"; - Dictionary result = null; - - result = PopulateRecursively(parent,result); - - return result; - } - - - - private static Dictionary PopulateRecursively(JToken parent, Dictionary result) - { - if (parent.HasValues) - { - foreach (JToken child in parent.Children()) - { - if (child is JProperty) - { - JProperty property = child as JProperty; - - if (result == null) - result = new Dictionary(); - - if(property.Value.HasValues) - { - PopulateRecursively(property.Value, result); - } - else - result.Add(property.Path, property.Value.ToString()); - } - - } - } - - return result; + return JArray.Parse(arrayTokens); } public static JArray GroupArray(JArray array, string groupingPropertyName, string groupedPropertyName) @@ -65,7 +33,7 @@ public static JArray GroupArray(JArray array, string groupingPropertyName, strin if (groupToken != null) { - object valueOfToken = Transformer.GetValue(groupToken); + object valueOfToken = Transformer.GetValue(groupToken, null); if (groupedPair.ContainsKey(valueOfToken.ToString())) { @@ -132,7 +100,7 @@ public static JArray GroupArrayMultipleProperties(JArray array, string[] groupin foreach (JToken groupToken in groupTokens) { - object valueOfToken = Transformer.GetValue(groupToken); + object valueOfToken = Transformer.GetValue(groupToken, null); if (key == string.Empty) key += valueOfToken; else diff --git a/Program.cs b/Program.cs deleted file mode 100644 index 5539cda..0000000 --- a/Program.cs +++ /dev/null @@ -1,211 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using JUST; -using System.IO; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace JUST.NET.Test -{ - class Program - { - public static void Main(string[] args) - { - string input = File.ReadAllText("Examples/Input.json"); - - string transformer = File.ReadAllText("Examples/Transformer_valueof.json"); - string transformedString = JsonTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - - transformer = File.ReadAllText("Examples/Transformer_valueofarray.json"); - transformedString = JsonTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - - transformer = File.ReadAllText("Examples/Transformer_copy.json"); - transformedString = JsonTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - transformer = File.ReadAllText("Examples/Transformer_replace.json"); - transformedString = JsonTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - transformer = File.ReadAllText("Examples/Transformer_delete.json"); - transformedString = JsonTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - - transformer = File.ReadAllText("Examples/Transformer_ifcondition.json"); - transformedString = JsonTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - transformer = File.ReadAllText("Examples/Transformer_string.json"); - transformedString = JsonTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - transformer = File.ReadAllText("Examples/Transformer_math.json"); - transformedString = JsonTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - transformer = File.ReadAllText("Examples/Transformer_aggregate.json"); - transformedString = JsonTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - transformer = File.ReadAllText("Examples/Transformer_arrayaggregate.json"); - transformedString = JsonTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - transformer = File.ReadAllText("Examples/Transformer_looping.json"); - transformedString = JsonTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - transformer = File.ReadAllText("Examples/Transformer_customfunction.json"); - transformedString = JsonTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - transformer = File.ReadAllText("Examples/Transformer_nestedfunctions.json"); - transformedString = JsonTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - transformer = File.ReadAllText("Examples/Transformer_xfunctions.json"); - transformedString = JsonTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - transformer = File.ReadAllText("Examples/Transformer_Existance.json"); - transformedString = JsonTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - transformer = File.ReadAllText("Examples/Transformer.json"); - transformedString = JsonTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - transformer = File.ReadAllText("Examples/DataTransformer.xml"); - transformedString = DataTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - transformer = File.ReadAllText("Examples/DataTransformer.csv"); - transformedString = DataTransformer.Transform(transformer, input); - Console.WriteLine("################################################################################################"); - Console.WriteLine(transformedString); - - transformer = File.ReadAllText("Examples/Transformer.json"); - transformedString = JsonConvert.SerializeObject - (JsonTransformer.Transform(JObject.Parse(transformer), JObject.Parse(input))); - Console.WriteLine(transformedString); - - - - Console.WriteLine("################################################################################################"); - string inputJson = File.ReadAllText("Examples/ValidationInput.json"); - string schemaJsonX = File.ReadAllText("Examples/SchemaX.json"); - string schemaJsonY = File.ReadAllText("Examples/SchemaY.json"); - - string InputToSplit = File.ReadAllText("Examples/InputToSplit.json"); - - List outputs = JsonTransformer.SplitJson(InputToSplit, "$.cars.Ford").ToList(); - - foreach (string output in outputs) - { - Console.WriteLine("-----------------------------------------------------"); - Console.WriteLine(output); - } - - Console.WriteLine("################################################################################################"); - - JsonValidator validator = new JsonValidator(inputJson); - validator.AddSchema("x", schemaJsonX); - validator.AddSchema("y", schemaJsonY); - - validator.Validate(); - - Console.WriteLine("################################################################################################"); - transformer = File.ReadAllText("Examples/Transformer_nestedloop.json"); - transformedString = JsonConvert.SerializeObject - (JsonTransformer.Transform(JObject.Parse(transformer), JObject.Parse(input))); - Console.WriteLine(transformedString); - - Console.WriteLine("################################################################################################"); - transformer = File.ReadAllText("Examples/Transformer_looptests.json"); - transformedString = JsonConvert.SerializeObject - (JsonTransformer.Transform(JObject.Parse(transformer), JObject.Parse(input))); - Console.WriteLine(transformedString); - - Console.WriteLine("################################################################################################"); - - string inputSpecial = File.ReadAllText("Examples/InputSpecial.json"); - transformer = File.ReadAllText("Examples/Transformer_customfunctionspecial.json"); - transformedString = JsonConvert.SerializeObject - (JsonTransformer.Transform(JObject.Parse(transformer), JObject.Parse(inputSpecial))); - Console.WriteLine(transformedString); - - Console.WriteLine("################################################################################################"); - - string inputUnordered = File.ReadAllText("Examples/Input_Unordered.json"); - transformer = File.ReadAllText("Examples/Transform_Unordered.json"); - transformedString = JsonConvert.SerializeObject - (JsonTransformer.Transform(JObject.Parse(transformer), JObject.Parse(inputUnordered))); - Console.WriteLine(transformedString); - - Console.WriteLine("################################################################################################"); - - string inputUnordered2 = File.ReadAllText("Examples/Input_Unordered_2.json"); - transformer = File.ReadAllText("Examples/Transform_Unordered_2.json"); - transformedString = JsonConvert.SerializeObject - (JsonTransformer.Transform(JObject.Parse(transformer), JObject.Parse(inputUnordered2))); - Console.WriteLine(transformedString); - - Console.WriteLine("################################################################################################"); - - - string inputDyn= File.ReadAllText("Examples/InputDynamic.json"); - transformer = File.ReadAllText("Examples/TransformDynamic.json"); - transformedString = JsonConvert.SerializeObject - (JsonTransformer.Transform(JObject.Parse(transformer), JObject.Parse(inputDyn))); - Console.WriteLine(transformedString); - - Console.WriteLine("################################################################################################"); - - transformer = File.ReadAllText("Examples/Transformer_externalmethods.json"); - transformedString = JsonConvert.SerializeObject - (JsonTransformer.Transform(JObject.Parse(transformer), JObject.Parse(input))); - Console.WriteLine(transformedString); - - Console.WriteLine("################################################################################################"); - - transformer = File.ReadAllText("Examples/Transformer_array.json"); - transformedString = JsonConvert.SerializeObject - (JsonTransformer.Transform(transformer, input)); - Console.WriteLine(transformedString); - - Console.WriteLine("################################################################################################"); - - transformer = File.ReadAllText("Examples/Transformer_array.json"); - transformedString = JsonConvert.SerializeObject - (JsonTransformer.Transform(JArray.Parse(transformer), input)); - Console.WriteLine(transformedString); - - Console.ReadLine(); - } - } -} diff --git a/README.md b/README.md index 7e759f5..e17ad98 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,8 @@ http://www.newtonsoft.com/json/help/html/QueryJsonSelectTokenJsonPath.htm Consider the input:- -``{ +```json +{ "menu": { "popup": { "menuitem": [ @@ -67,22 +68,27 @@ Consider the input:- ] } } -}`` +} +``` Transformer:- -``{ +```json +{ "result": { "Open": "#valueof($.menu.popup.menuitem[?(@.value=='Open')].onclick)", "Close": "#valueof($.menu.popup.menuitem[?(@.value=='Close')].onclick)" } -}`` +} +``` Output:- -``{ +```json +{ "result":{"Open": "OpenDoc()", "Close": "CloseDoc()"} -}`` +} +``` ## ifcondition @@ -95,26 +101,32 @@ All four of the parameters can be a 'valueof' expressions or constants. Consider the input:- -``{ +```json +{ "menu": { "id" : "github", "repository" : "JUST" } -}`` +} +``` Transformer:- -``{ +```json +{ "ifconditiontesttrue": "#ifcondition(#valueof($.menu.id),github,#valueof($.menu.repository),fail)", "ifconditiontestfalse": "#ifcondition(#valueof($.menu.id),xml,#valueof($.menu.repository),fail)" -}`` +} +``` Output:- -``{ +```json +{ "ifconditiontesttrue":"JUST", "ifconditiontestfalse":"fail" -}`` +} +``` ## string and math functions @@ -131,14 +143,17 @@ At the moment only the basic and often used string and math functions are provid Consider the input:- -``{ +```json +{ "stringref": "thisisandveryunuasualandlongstring", "numbers": [ "1", "2", "3", "4", "5" ] -}`` +} +``` Transformer:- -``{ +```json +{ "stringresult": { "lastindexofand": "#lastindexof(#valueof($.stringref),and)", "firstindexofand": "#firstindexof(#valueof($.stringref),and)", @@ -151,11 +166,13 @@ Transformer:- "multiply": "#multiply(2,#valueof($.numbers[2]))", "divide": "#divide(9,3)" } -}`` +} +``` Output:- -``{"stringresult": +```json +{"stringresult": { "lastindexofand":"21", "firstindexofand":"6", @@ -169,7 +186,8 @@ Output:- "multiply":"6", "divide":"3" } -}`` +} +``` ## Opearators @@ -185,14 +203,17 @@ The following operators have been added to compare strings and numbers :- Consider the input:- -``{ +```json +{ "d": [ "one", "two", "three" ], "numbers": [ "1", "2", "3", "4", "5" ] -}`` +} +``` Transformer:- -``{ +```json +{ "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)", @@ -202,11 +223,24 @@ Transformer:- "one_stringequals": "#ifcondition(#stringequals(#valueof($.d[0]),one),true,yes,no)", "one_stringcontains": "#ifcondition(#stringcontains(#valueof($.d[0]),n),true,yes,no)" } -}`` +} +``` Output:- -``{"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"}} +```json +{ + "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" + } +} +``` ## Aggregate functions @@ -220,30 +254,36 @@ The following aggregate functions are provided for single dimensional arrays:- Consider the input:- -``{ +```json +{ "d": [ "one", "two", "three" ], "numbers": [ "1", "2", "3", "4", "5" ] -}`` +} +``` Transformer:- -``{ +```json +{ "conacted": "#concatall(#valueof($.d))", "sum": "#sum(#valueof($.numbers))", "avg": "#average(#valueof($.numbers))", "min": "#min(#valueof($.numbers))", "max": "#max(#valueof($.numbers))" -}`` +} +``` Output:- -``{ +```json +{ "conacted":"onetwothree", "sum":"15", "avg":"3", "min":"1", "max":"5" -}`` +} +``` ## Aggregate functions for multidimensional arrays:- @@ -256,7 +296,8 @@ These functions are essentially the same as the above ones, the only difference Consider the input:- -``{ +```json +{ "x": [ { "v": { @@ -280,27 +321,54 @@ Consider the input:- } } ] -}`` +} +``` Transformer:- -``{ +```json +{ "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)" -}`` +} +``` Output:- -``{ +```json +{ "arrayconacted":"a1,a2,a3b1,b2c1,c2,c3", "arraysum":"60", "arrayavg":"20", "arraymin":"1", "arraymax":"3" -}`` +} +``` + +## Select array using a json path + +`getarray(, )` allows to select an array by using json path. The search is relative to the start object. + +Transformer:- + +```json +{ + "array": #getarray(#getroot(), $.root.items.inhabitant[?(@.firstname=='Max')])) +} +``` + +## Document navigation + +**getroot** + +Returns the root document. + +**getparent** + + ## Bulk functions @@ -317,7 +385,8 @@ These are the bulk functions provided as of now:- Cosider the input:- -``{ +```json +{ "tree": { "branch": { "leaf": "green", @@ -327,18 +396,22 @@ Cosider the input:- }, "ladder": {"wood": "treehouse" } } -}`` +} +``` Transformer:- -``{ +```json +{ "#": [ "#copy($)", "#delete($.tree.branch.bird)", "#replace($.tree.branch.extra,#valueof($.tree.ladder))" ], "othervalue" : "othervalue" -}`` +} +``` Output:- -``{ +```json +{ "othervalue":"othervalue", "tree":{ "branch":{ @@ -352,7 +425,8 @@ Output:- "wood":"treehouse" } } -}`` +} +``` ## Array looping @@ -371,7 +445,8 @@ These are the functions provided for this pupose:- Cosider the input:- -``{ +```json +{ "tree": { "branch": { "leaf": "green", @@ -396,11 +471,13 @@ Cosider the input:- "language": "swedish" } }] -}`` +} +``` Transformer:- -``{ +```json +{ "iteration": { "#loop($.numbers)": { "CurrentValue": "#currentvalue()", @@ -418,11 +495,13 @@ Transformer:- } }, "othervalue": "othervalue" -}`` +} +``` Output:- -``{"iteration":[ +```json +{"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"}, @@ -433,12 +512,15 @@ Output:- {"CurrentValue":"UK","CurrentIndex":"1","IsLast":"no","LastValue":"swedish"}, {"CurrentValue":"Sweden","CurrentIndex":"2","IsLast":"yes","LastValue":"swedish"} ], -"othervalue":"othervalue"}`` +"othervalue":"othervalue"} +``` ## Nested array looping (looping within context) A new function `loopwithincontext` has been introduced to be able to loop withing the context of an outer loop. Cosider the input:- -``{ + +```json +{ "NestedLoop": { "Organization": { "Employee": [ @@ -467,10 +549,13 @@ Cosider the input:- ] } } -}`` +} +``` + Transformer:- -``{ +```json +{ "hello": { "#loop($.NestedLoop.Organization.Employee)": { "CurrentName": "#currentvalueatpath($.Name)", @@ -481,17 +566,20 @@ Transformer:- } } } -}`` +} +``` Output:- -``{ +```json +{ "hello": [ {"CurrentName":"E2","Details":[{"CurrentCountry":"Iceland"}]}, {"CurrentName":"E1","Details":[{"CurrentCountry":"Denmark"}]} ] -}`` +} +``` ## Array grouping @@ -501,7 +589,8 @@ grouparrayby(path,groupingElementName,groupedElementName) Input:- -``{ +```json +{ "Forest": [ { "type": "Mammal", @@ -534,17 +623,21 @@ Input:- "name": "Dog" } ] -}`` +} +``` Transformer:- -``{ +```json +{ "Result": "#grouparrayby($.Forest,type,all)" -}`` +} +``` Output:- -``{ +```json +{ "Result":[ { "type":"Mammal", @@ -586,13 +679,15 @@ Output:- ] } ] -}`` +} +``` You can group using multiple "grouping elements". They should be seperated by a semicolon (:) Input:- -``{ +```json +{ "Vehicle": [ { "type": "air", @@ -625,17 +720,21 @@ Input:- "name": "truck" } ] -}`` +} +``` Transformer:- -``{ +```json +{ "Result": "#grouparrayby($.Vehicle,type:company,all)" -}`` +} +``` Output:- -``{ +```json +{ "Result":[ { "type":"air", @@ -680,7 +779,8 @@ Output:- ] } ] -}`` +} +``` ## Calling Custom functions @@ -694,7 +794,8 @@ A custom function is called using the following syntax:- Consider the following input:- -``{ +```json +{ "tree": { "branch": { "leaf": "green", @@ -702,13 +803,16 @@ Consider the following input:- "bird": "crow" } } -}`` +} +``` Transformer:- -``{ +```json +{ "Season": "#customfunction(JUST.NET.Test,JUST.NET.Test.Season.findseason,#valueof($.tree.branch.leaf),#valueof($.tree.branch.flower))" -}`` +} +``` Custom function:- @@ -721,7 +825,9 @@ Custom function:- }` Output:- -``{"Season":"summer"}`` +```json +{"Season":"summer"} +``` ## Calling User Defined methods by name @@ -735,7 +841,8 @@ Here's the syntax:- Consider the following input:- -``{ +```json +{ "season": { "characteristics": { "hot": true, @@ -743,16 +850,21 @@ Consider the following input:- "randomDay": "2018-08-01T00:00:00.000Z" } } -}`` +} +``` Transformer:- -``{ +```json +{ "summer": "#ExternalMethods::SeasonsHelper.Season::IsSummer(#valueof($.season.characteristics.hot),#valueof($.season.characteristics.averageDaysOfRain),#valueof($.season.characteristics.randomDay))" -}`` +} +``` Output:- -``{"summer": true}`` +```json +{"summer": true} +``` ## Complex nested functions @@ -760,17 +872,20 @@ You can easily nest functions to do complex transformations. An example of such Consider the following input:- -``{ +```json +{ "Name": "Kari", "Surname": "Nordmann", "MiddleName": "Inger", "ContactInformation": "Karl johans gate:Oslo:88880000" , "PersonalInformation": "45:Married:Norwegian" -}`` +} +``` Transformer:- -``{ +```json +{ "FullName": "#concat(#concat(#concat(#valueof($.Name), ),#concat(#valueof($.MiddleName), )),#valueof($.Surname))", "Contact Information": { "Street Name": "#substring(#valueof($.ContactInformation),0,#firstindexof(#valueof($.ContactInformation),:))", @@ -780,12 +895,14 @@ Transformer:- "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),:)))" - }`` + "Ethnicity": "#substring(#valueof($.PersonalInformation),#add(#lastindexof(#valueof($.PersonalInformation),:),1),#subtract(#lastindexof(#valueof($.PersonalInformation),),#lastindexof(#valueof($.PersonalInformation),:)))" +} +``` Output:- -``{ +```json +{ "FullName":"Kari Inger Nordmann", "Contact Information":{ "Street Name":"Karl johans gate", @@ -797,7 +914,8 @@ Output:- "Civil Status":"Married", "Ethnicity":"Norwegian" } -}`` +} +``` ## Multiple argument & constant functions @@ -812,24 +930,30 @@ Hence, the following 3 functions have been introduced:- Consider the following input:- -``{ +```json +{ "Name": "Kari", "Surname": "Nordmann", "MiddleName": "Inger", "ContactInformation": "Karl johans gate:Oslo:88880000" , "PersonalInformation": "45:Married:Norwegian" -}`` +} +``` Transformer:- -``{ +```json +{ "FullName": "#xconcat(#valueof($.Name),#constant_comma(),#valueof($.MiddleName),#constant_comma(),#valueof($.Surname))", "AgeOfParents": "#xadd(#valueof($.AgeOfMother),#valueof($.AgeOfFather))" -}`` +} +``` Output:- -``{"FullName":"Kari,Inger,Nordmann","AgeOfParents":"67"}`` +```json +{"FullName":"Kari,Inger,Nordmann","AgeOfParents":"67"} +``` ## Check for existance @@ -840,30 +964,36 @@ The following two functions have been added to check for existance:- Consider the following input:- -``{ +```json +{ "BuyDate": "2017-04-10T11:36:39+03:00", "ExpireDate": "" -}`` +} +``` Transformer:- -``{ +```json +{ "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)" -}`` +} +``` Output:- -``{"BuyDateString":"Buy Date : 2017-04-10T11:36:39+03:00", +```json +{"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" -}`` +} +``` ## Conditional transformation @@ -873,16 +1003,19 @@ The function takes an expression as argument which should evaluate to a boolean Consider the following input:- -``{ +```json +{ "Tree": { "Branch": "leaf", "Flower": "Rose" } -}`` +} +``` Transformer:- -``{ +```json +{ "Result": { "Header": "JsonTransform", "#ifgroup(#exists($.Tree.Branch))": { @@ -892,10 +1025,12 @@ Transformer:- } } } -}`` +} +``` Output:- -``{ +```json +{ "Result":{ "Header":"JsonTransform", "State":{ @@ -903,13 +1038,15 @@ Output:- "Value2":"Rose" } } -}`` +} +``` Now, for the same input if we use the following transformer, we get a diferent output. Transformer:- -``{ +```json +{ "Result": { "Header": "JsonTransform", "#ifgroup(#exists($.Tree.Root))": { @@ -919,14 +1056,17 @@ Transformer:- } } } -}`` +} +``` Output:- -``{ +```json +{ "Result":{ "Header":"JsonTransform" } -}`` +} +``` ## Dynamic Properties @@ -935,27 +1075,33 @@ We can now create dynamic properties using the *eval* function. The function tak Consider the following input:- -``{ +```json +{ "Tree": { "Branch": "leaf", "Flower": "Rose" } -}`` +} +``` Transformer:- -``{ +```json +{ "Result": { "#eval(#valueof($.Tree.Flower))": "x" } -}`` +} +``` Output:- -``{ +```json +{ "Result":{ "Rose":"x" } -}`` +} +``` @@ -983,15 +1129,18 @@ In the above case if the validation is un-successful an exception will be thrown Consider the validation input:- -``{ +```json +{ "x.tree": { "x.branch": { "x.leaf": "1" } }, "x.child": 1, "y.animal": 1 -}`` +} +``` Schema X JSON:- -``{ +```json +{ "properties": { "tree": { "type": "object", @@ -1007,16 +1156,18 @@ Schema X JSON:- }, "child": { "type": "string" } } -}`` +} +``` Schema Y JSON:- -``{ +```json +{ "properties": { "animal": { "type": "string" } } } -`` +``` The exception message thrown in the above case would be:- @@ -1033,7 +1184,9 @@ Two new functions have been added for this purpose:- `public static IEnumerable SplitJson(JObject input, string arrayPath)` Consider the input:- -``{ + +```json +{ "cars": { "Ford": [ { @@ -1056,7 +1209,8 @@ Consider the input:- "firstName": "John", "lastName": "Smith", } -}`` +} +``` Below is a sample code which splits the above input:- @@ -1093,7 +1247,9 @@ Sample code to transform from JSON to XML:- ``string transformedString = DataTransformer.Transform(transformer, input);`` Input.json:- -``{ + +```json +{ "menu": { "id": { "file": "csv" @@ -1163,11 +1319,13 @@ Input.json:- "BuyDate": "2017-04-10T11:36:39+03:00", "ExpireDate": "", "LogId": 5000510625 -}`` +} +``` DataTransformer.xml:- -`` +```xml + #ifcondition(#valueof($.menu.id.file),csv,#valueof($.menu.value.Window),fail) @@ -1218,10 +1376,12 @@ DataTransformer.xml:- #valueof($.LogId) } -`` + +``` Output:- -`` +```xml + popup @@ -1299,7 +1459,8 @@ Output:- 5000510625 -`` + +``` ### Example for JSON to CSV @@ -1314,8 +1475,11 @@ DataTransformer.csv:- ``"#loop($.numbers)": {#currentvalue(),#currentindex(),#ifcondition(#currentindex(),#lastindex(),yes,no),#lastvalue(),#valueof($.LogId)}`` Output:- -``1,0,no,5,5000510625 + +```csv +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`` +5,4,yes,5,5000510625 +``` diff --git a/Season.cs b/Season.cs deleted file mode 100644 index 57167a5..0000000 --- a/Season.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -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"; - } - - public static object serialize(string inObj) - { - JObject jObj = JObject.FromObject( JsonConvert.DeserializeObject(inObj)); - - JArray array = new JArray(); - - foreach(JProperty property in jObj.Children()) - { - JObject nameValObj = new JObject(); - nameValObj.Add("name", property.Name); - nameValObj.Add("value", property.Value); - - array.Add(nameValObj); - } - - JObject returnObj = new JObject(); - returnObj.Add("namevaluecollection",array); - - return returnObj; - } - } -} diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 0000000..1539cb5 --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,62 @@ +trigger: + branches: + include: + - master + - dev + paths: + include: + - src/* + - test/* + - azure-pipelines.yml + +pr: + branches: + include: + - '*' + +pool: + vmImage: 'windows-latest' + +variables: + buildConfiguration: 'Release' + +steps: +- task: NuGetToolInstaller@1 + inputs: + versionSpec: '5.x' + +- task: NuGetCommand@2 + inputs: + command: 'restore' + restoreSolution: 'JUST.NET.sln' + feedsToUse: 'select' + vstsFeed: 'f7087ef5-bf6f-48b2-8b8b-5e513f4a7a9e' + +- task: MSBuild@1 + inputs: + solution: 'JUST.NET.sln' + configuration: '$(buildConfiguration)' + +- task: DotNetCoreCLI@2 + displayName: 'Run unit tests - $(buildConfiguration)' + inputs: + command: 'test' + arguments: '--configuration $(buildConfiguration) /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=$(Build.SourcesDirectory)/TestResults/Coverage/' + publishTestResults: true + projects: '**/*.Test.csproj' + +- task: NuGetCommand@2 + inputs: + command: 'pack' + packagesToPack: '**/JUST.net.csproj;!**/JUST.NET.csproj' + configuration: '$(buildConfiguration)' + versioningScheme: 'off' + +- task: NuGetCommand@2 + condition: eq(variables['Build.SourceBranch'], 'refs/heads/master') + inputs: + command: 'push' + packagesToPush: '$(Build.ArtifactStagingDirectory)/JUST.net.*.nupkg;!$(Build.ArtifactStagingDirectory)/JUST.net.*.symbols.nupkg' + nuGetFeedType: 'internal' + publishVstsFeed: 'f7087ef5-bf6f-48b2-8b8b-5e513f4a7a9e' + allowPackageConflicts: true diff --git a/packages.config b/packages.config index 0033278..c983e22 100644 --- a/packages.config +++ b/packages.config @@ -1,7 +1,7 @@  - - + +