Extract Items in Nested Json Array - c#

How can I extract items from nested Json Array using Newtonsoft.Json functions or methods? I have a Json like this
{
"Bounds": {
"TextLength": 1379
},
"DocumentTypeName": "Invoice",
"DocumentTypeField": {
"Value": "Invoice",
"Confidence": 1
},
"Fields": [
{
"FieldId": "RPA.DocumentUnderstanding.Invoice.LineItems",
"FieldName": "Line Items",
"Values": [
{
"Components": [
{
"FieldId": "RPA.DocumentUnderstanding.Invoice.LineItems.Body",
"FieldName": "Body",
"Values": [
{
"Components": [
{
"FieldId": "RPA.DocumentUnderstanding.Invoice.LineItems.Item",
"FieldName": "Item",
"Values": [
{
"Components": [],
"Value": "Film 4C for the publication \"Racing World\" Visual: PNSP 02 05 Ref. 2004/021 Graphic designer honoraries 560010",
"Confidence": 0.962736368
}
]
},
{
"FieldId": "RPA.DocumentUnderstanding.Invoice.LineItems.UnitPrice",
"FieldName": "Unit Price",
"Values": [
{
"Components": [],
"Value": "400.00",
"Confidence": 0.9779528
}
]
}
],
"Confidence": 0.9432406
}]}],
"Confidence": 0.920952857}]}]}
and I want to extract the red highlighted fields from it.
Any help will be much appreciated.
Thanks

Since not deserializing is not a requirement you can do that. Just create C# object that has the exact same structure as your JSON and then do
var yourObject = JsonConvert.DeserializeObject<YourCSharpClassHere>(yourJsonString);
Then it's just a simple matter of getting the values
var fieldName = yourObject.Values[0].Components[0].Values[0].Components[0].FieldName

You can use JSON Query
Example
var fieldNames = o.SelectTokens("Values[*].Components[*].Values[*].Components[*].FieldName");

Related

Get nodes and relationships at n-hops away from a root node in a Neo4j graph

I want to query a Neo4j graph for nodes and their relationships at a given hop from a root node. I could get the nodes using apoc.neighbors.byhop, though not sure how I can get relationships between nodes.
Specifically, in the following graph, I'm interested to know that A is connected to C through B1 or B2. The output of apoc.neighbors.byhop does not seem to contain this information.
merge (p1:Person {label:"A"})
merge (p2:Person {label:"B1"})
merge (p3:Person {label:"B2"})
merge (p4:Person {label:"C"})
merge (p1)-[:Knows]->(p2)
merge (p1)-[:Knows]->(p3)
merge (p2)-[:Knows]->(p4)
To retrieve nodes at an n-hop distance:
match (p:Person {label:"A"})
call apoc.neighbors.byhop(p, "Knows", 3)
yield nodes
return nodes
Which returns an object as the following that does not include relationship information.
[
[
{
"identity":11,
"labels":[
"Person"
],
"properties":{
"label":"B1"
}
},
{
"identity":12,
"labels":[
"Person"
],
"properties":{
"label":"B2"
}
}
],
[
{
"identity":0,
"labels":[
"Person"
],
"properties":{
"label":"C"
}
}
]
]
I'm interfacing with Neo4j through its .NET driver.
That APOC function (apoc.neighbors.byhop) only returns nodes and NOT relationships. I tried replicating the same APOC function and returns the relationships in the path.
MATCH path=(p:Person {label:"A"})-[:Knows*1..]->(p2:Person)
WITH [n in nodes(path) where n <> p | n] as nodes, relationships(path) as relationships
WITH size(nodes) as cnt, collect(nodes[-1]) as nodes, collect(distinct relationships[-1]) as relationships
RETURN nodes, relationships
Below is the result:
[
{
"nodes": [
{
"identity": 2,
"labels": [
"Person"
],
"properties": {
"label": "B1"
}
},
{
"identity": 3,
"labels": [
"Person"
],
"properties": {
"label": "B2"
}
}
],
"relationships": [
{
"identity": 0,
"start": 1,
"end": 2,
"type": "Knows",
"properties": {
}
},
{
"identity": 1,
"start": 1,
"end": 3,
"type": "Knows",
"properties": {
}
}
]
},
{
"nodes": [
{
"identity": 4,
"labels": [
"Person"
],
"properties": {
"label": "C"
}
}
],
"relationships": [
{
"identity": 2,
"start": 2,
"end": 4,
"type": "Knows",
"properties": {
}
}
]
}
]
Something like this in pure Cypher will show you all relationships between nodes. You can tweak the node properties and relationship names as you'd like.
MATCH path = (p:Person)-[*1..]->(p2:Person) RETURN p, relationships(path), p2

Azure Cosmos DB Add Composite Index for Array of String

I am trying to add a new composite index to do multiple fields search.
I would like to know thing to consider while adding a new Composite index and will it work for array string?
Sample Cosmos Document
{
"id": "ed78b9b5-764b-4ebc-a4f2-6b764679",
"OrderReference": "X000011380",
"SetReferences": [
"000066474884"
],
"TransactionReference": "ed78b9b5-764b-4ebc-6b7644f06679",
"TransactionType": "Debit",
"Amount": 73.65,
"Currency": "USD",
"BrandCode": "TestBrand",
"PartitionKey": "Test-21052020-255",
"SettlementDateTime": "2020-05-21T04:35:35.133Z",
"ReasonCode": "TestReason",
"IsProcessed": true,
}
My Existing index policy
{
"indexingMode": "consistent",
"automatic": true,
"includedPaths": [
{
"path": "/PartitionKey/?"
},
{
"path": "/BrandCode/?"
}
],
"excludedPaths": [
{
"path": "/*"
},
{
"path": "/\"_etag\"/?"
}
],
"compositeIndexes": [
[
{
"path": "/PartitionKey",
"order": "ascending"
},
{
"path": "/IsProcessed",
"order": "ascending"
}
]
]
}
To fetch data from Array of string SettlementReferences, IsProcessed, ReasonCode.
SELECT * FROM c WHERE ARRAY_CONTAINS(c.SettlementReferences, '00884') and c.IsProcessed = true and c.ReasonCode = 'TestReason'
I am planning to add the following policy
{
"indexingMode": "consistent",
"automatic": true,
"includedPaths": [
{
"path": "/PartitionKey/?"
},
{
"path": "/BrandCode/?"
}
],
"excludedPaths": [
{
"path": "/*"
},
{
"path": "/\"_etag\"/?"
}
],
"compositeIndexes": [
[
{
"path": "/PartitionKey",
"order": "ascending"
},
{
"path": "/IsProcessed",
"order": "ascending"
}
],
[
{
"path": "/SettlementReferences",
"order": "ascending"
},
{
"path": "/IsProcessed",
"order": "ascending"
},
{
"path": "/ReasonCode",
"order": "ascending"
}
]
]
}
Please let me know if this change is sufficient?
Moreover, I tried to compare RU's before and after the change. I don't see any massive difference, both coming around 133.56 Rus.
Is there anything more I need to consider for optimized performance?
Composite Indexes will not help with this query and overall don't have any impact on equality statements. They are useful when doing order by's in your queries. This is why you don't see any RU/s reduction in your query. However, you will notice increased RU/s on writes.
If you want to improve your query performance you should add any properties in your where clauses into the "includedPaths" in your index policy.
Another thing to point out too is generally it is a best practice to by default index everything and selectively add properties to excludedPaths. This way, if your schema changes it will be indexed automatically without having to rebuilt your index.
As mark mentioned we need to add include path for Array "/SettlementReferences /[]/?". After adding my number of Ru's reduced from 115 to 5 ru's.

How to extract ID from the following JSON Object in C#?

I want to extract all IDs from the below object using c#.
in need of extracting a response value in a visual studio webtest.
The JSON is obtained using extract event.
{
"d": [
{
"__type": "QuestionZoneEditor.Entities.QuestionTag",
"Id": 2080,
"Name": "01",
"Items": [
"1a",
"1b",
"1c",
"1d"
]
},
{
"__type": "QuestionZoneEditor.Entities.QuestionTag",
"Id": 2081,
"Name": "02",
"Items": [
"2a(i)",
"2a(ii)",
"2b",
"2c"
]
},
{
"__type": "QuestionZoneEditor.Entities.QuestionTag",
"Id": 2082,
"Name": "03",
"Items": [
"3a",
"3b",
"3c"
]
}
}
]
}
Deserialize it to JObject after that take all JObject from the JArray and print the Id
var result = JsonConvert.DeserializeObject<JObject>(json);
foreach(JObject obj in result["d"])
{
Console.WriteLine(obj["Id"]);
}
Full example: dotNetFiddle

Get Token in Json

I have a problem with this JSON to get the second level in JArray:
{
"Level1": {
"Level2": [{
"id": "Chart",
"Box": [{
"id": "1",
"value": "10"
},{
"id": "2",
"value": "20"
}]
}]
}
}
And I want to get completly the level 2 like Array in this way:
JArray contasdasd = _jsonMaster["Level1"]["Level2"] as JArray;
I get :
{
"id": "Chart",
"Box": [{
"id": "1",
"value": "10"
},{
"id": "2",
"value": "20"
}]
}
and I want:
"Level2": [{
"id": "Chart",
"Box": [{
"id": "1",
"value": "10"
},{
"id": "2",
"value": "20"
}]
}]
Is there any way to get the level 2 ?
Surely you just do
var level1 = _jsonMaster["Level1"];
The problem is that you've gone one level too far.
The object you are interested in "Level2": [...] is not a JArray itself but is a JProperty. You can get it by searching properties of Level1 but keep in mind you will now have a JProperty rather than a JArray. The Value of that result will be the JArray you were getting in your current code.
JProperty contasdasd = _jsonMaster["Level1"].First(o => (o as JProperty).Name == "Level2") as JProperty;
Console.WriteLine(contasdasd.ToString()); // Will be what you are looking for
Console.WriteLine(contasdasd.GetType()); // Will return JProperty
Console.WriteLine(contasdasd.Value.GetType()); // Will return JArray

Deserialize Dynamic Json string using Newtonsoft JSON.NET

I have a JSON string that I'm getting from Facebook API, in which I have a node whose name changes according to its content, for example some time it is 45, or 58 etc.
It could be any number.
I want its value. How to get it?
Example:
{
"data": [
{
"id": "1492292372_10201810786059989",
"created_time": "2014-04-05T09:00:54+0000"
},
{
"id": "1492292372_10201804679827337",
"created_time": "2014-04-04T07:29:07+0000"
},
{
"id": "1492292372_10201804649306574",
"created_time": "2014-04-04T07:10:33+0000"
},
{
"id": "1492292372_10201801316823264",
"created_time": "2014-04-03T18:31:50+0000"
},
{
"id": "1492292372_10201798962284402",
"created_time": "2014-04-03T06:24:47+0000"
},
{
"message_tags": {
"0": [
{
"id": "1492292372",
"name": "Yawar Sohail",
"type": "user",
"offset": 0,
"length": 12
}
],
"15": [
{
"id": "1489845168",
"name": "Zeeshan Anjum",
"type": "user",
"offset": 15,
"length": 13
}
]
},
"id": "1492292372_10201796274777216",
"created_time": "2014-04-02T17:57:05+0000"
},
{
"id": "1492292372_10201794080482360",
"created_time": "2014-04-02T07:26:23+0000"
},
Inside message_tags there are two nodes [0 and 15] they dynamically changes according to their offset values. I want names, type and ids inside these nodes.
You can deserialize your JSON into an ExpandoObject:
var converter = new ExpandoObjectConverter();
dynamic obj = JsonConvert.DeserializeObject<ExpandoObject>(json, converter);
Which dynamically adds members to your object at runtime, and allows you to iterate over them as described in this answer:
foreach (var prop in obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
Console.WriteLine("Name: {0}, Value: {1}",prop.Name, prop.GetValue(obj,null));
}
That way you can iterate over obj.message_tags to get the individual messages, and obtain all their details respectively.

Categories

Resources