My JSON looks like this sometime, which has name key missing in 2nd object. It may be any key in thousands of JSON file I read dynamically to extract fields required using JSON Path queries.
void Main()
{
string jsonText = #"[
{
'rank': 1,
'name': 'name 1',
'year': '1991'
},
{
'rank': 2,
'year': '1992'
},
{
'rank': 3,
'name': 'name 3',
'year': '1993'
}
]";
JToken json = JToken.Parse(jsonText);
List<Fields> fields = new List<Fields>
{
new Fields
{
name = "rank",
path = "$.[*].rank",
result = new List<string>()
},
new Fields
{
name = "name",
path = "$.[*].name",
result = new List<string>()
},
new Fields
{
name = "year",
path = "$.[*].year",
result = new List<string>()
}
};
foreach(var field in fields)
{
var result = json.SelectTokens(field.path);
foreach (var token in result)
{
if (token is JObject || token is JArray)
{
field.result.Add(token.ToString(Newtonsoft.Json.Formatting.None));
}
else
{
field.result.Add(token.ToString());
}
}
}
fields.Dump();
}
public class Fields
{
public string name { get; set; }
public string path { get; set; }
public List<string> result {get; set;}
}
Which results in below incorrect table as the "name 3" moved one row up on 2nd row. While it should be on 3rd row and the 2nd row should have null value.
Here is one way (Updated to fix trailing missing fields):
void Main()
{
string jsonText = #"[
{
'rank': 1,
'name': 'name 1',
'year': '1991'
},
{
'rank': 2,
'year': '1992'
},
{
'rank': 3,
'name': 'name 3',
}
]";
JToken json = JToken.Parse(jsonText);
List<Fields> fields = new List<Fields>
{
new Fields
{
name = "rank",
path = "$.[*].rank",
result = new List<string>()
},
new Fields
{
name = "name",
path = "$.[*].name",
result = new List<string>()
},
new Fields
{
name = "year",
path = "$.[*].year",
result = new List<string>()
}
};
var max = json.SelectTokens("$.[*]").Count().Dump();
foreach (var field in fields)
{
var result = json.SelectTokens(field.path);
var index = 0;
foreach (var token in result)
{
while(!token.Path.StartsWith($"[{index++}]"))
field.result.Add(null);
if (token is JObject || token is JArray)
{
field.result.Add(token.ToString(Newtonsoft.Json.Formatting.None));
}
else
{
field.result.Add(token.ToString());
}
}
field.result.AddRange(Enumerable.Range(0,max-result.Count()).Select(z=>(string)null));
}
fields.Dump();
}
public class Fields
{
public string name { get; set; }
public string path { get; set; }
public List<string> result { get; set; }
}
Related
I am trying to delete this header "vendor": and { } branch from Json formated output.
The reason to delete is to map these three fields names ("RECORDNO".."NAME") to SQL table.
Bottom is expected output:
Bottom is C# code that iterates thru each ones and populates the result, and later uses JsonCovert to format output in Json format.
public static string Run(ILogger logger)
{
OnlineClient client = Bootstrap.Client(logger);
ReadByQuery query = new ReadByQuery()
{
ObjectName = "VENDOR",
PageSize = 600,
Fields =
{
"RECORDNO",
"VENDORID",
"NAME"
}
};
logger.LogInformation("Executing query to Intacct API");
Task<OnlineResponse> task = client.Execute(query);
task.Wait();
OnlineResponse response = task.Result;
Result result = response.Results[0];
LogManager.Flush();
int i = 1;
while (result.NumRemaining > 0 && i <= 1 && !string.IsNullOrEmpty(result.ResultId))
{
i++;
ReadMore more = new ReadMore()
{
ResultId = result.ResultId
};
Task<OnlineResponse> taskMore = client.Execute(more);
taskMore.Wait();
OnlineResponse responseMore = taskMore.Result;
Result resultMore = responseMore.Results[0];
dynamic resultJson =
JsonConvert.DeserializeObject(JsonConvert.SerializeObject(result.Data));
string resultJsonString = resultJson.ToString();
return resultJsonString;
}
return "";
}
I am not fluent in C# so I am not sure how to express to delete the "vendor:" portion from 'query'.
I am sure there are a lot of unnecessary lines from this C# code which could be deleted (to clean up).
What is expression to delete "vendor": and { } branch?
This is updated code based on the comment from #Serge.
int i = 1;
while (result.NumRemaining > 0 && i <= 1 && !string.IsNullOrEmpty(result.ResultId))
{
i++;
dynamic resultJson =
JsonConvert.DeserializeObject(JsonConvert.SerializeObject(result.Data));
string resultJsonString = resultJson.ToString();
var jsonArray = JArray.Parse(resultJsonString);
var newJsonArray = jsonArray.SelectTokens("$..VENDOR");
var result1 = JsonConvert.SerializeObject(newJsonArray, Newtonsoft.Json.Formatting.Indented);
return result1;
}
When I modified like this way, I got no data output (as shown below).
[ ]
What is proper way (area) to put the bottom code?
var jsonArray=JArray.Parse(json);
var newJsonArray = jsonArray.SelectTokens("$..VENDOR");
var result= JsonConvert.SerializeObject(newJsonArray, Newtonsoft.Json.Formatting.Indented);
You could create a new JObject assigning to it the JObject value available at the "vendor" field.
You could do something like this:
JObject changed = jobj["vendor"].Value<JObject>();
Here is an example:
JObject toChange = new JObject();
toChange["vendor"] = new JObject();
toChange["vendor"]["fieldA"] = "value";
toChange["vendor"]["fieldB"] = "value";
JObject changed = toChange["vendor"].Value<JObject>();
Console.WriteLine(toChange.ToString());
Console.WriteLine(changed.ToString());
FROM THIS:
{
"vendor": {
"fieldA": "value",
"fieldB": "value"
}
}
YOU'D GET THIS:
{
"fieldA": "value",
"fieldB": "value"
}
try this using Newtonsoft.Json
using Newtonsoft.Json;
....
var json="[{\"VENDOR\":{\"RECORDNO\":\"1\",\"VENDORID\":\"ID1\",\"NAME\":\"Name1\"}},{\"VENDOR\":{\"RECORDNO\":\"2\",\"VENDORID\":\"ID2\",\"NAME\":\"Name2\"}},{\"VENDOR\":{\"RECORDNO\":\"3\",\"VENDORID\":\"ID3\",\"NAME\":\"Name3\"}}]"
var jsonArray=JArray.Parse(json);
var newJsonArray = jsonArray.SelectTokens("$..VENDOR");
var result= JsonConvert.SerializeObject(newJsonArray, Newtonsoft.Json.Formatting.Indented);
result
[ {
"RECORDNO": "1",
"VENDORID": "ID1",
"NAME": "Name1"
},
{
"RECORDNO": "2",
"VENDORID": "ID2",
"NAME": "Name2"
},
{
"RECORDNO": "3",
"VENDORID": "ID3",
"NAME": "Name3"
} ]
or you can create classes and have typed c# list
var jsonDeserialized=JsonConvert.DeserializeObject<VendorRoot[]>(json);
List<VENDOR> newJsonList = jsonDeserialized.Select(d => d.VENDOR ).ToList();
var result= JsonConvert.SerializeObject(newJsonList, Newtonsoft.Json.Formatting.Indented);
classes
public class VendorRoot
{
public VENDOR VENDOR { get; set; }
}
public class VENDOR
{
public string RECORDNO { get; set; }
public string VENDORID { get; set; }
public string NAME { get; set; }
}
Could someone helpe me?
How can I code 'Shippings' class as an Array to get the json example below?
{
"seller_id": "123",
"amount": 100,
"order": {
"order_id": "1111",
"sales_tax": 0,
"product_type": "service"
},
"shippings": [{
"first_name": "John",
"phone_number": "5551999887766",
"shipping_amount": 3000,
"address": {
"street": "Street 35 Conts",
"number": "1000",
"complement": "ap1",
"postal_code": "90230060"
}
}],
"credit": {
"delayed": false,
"authenticated": false
}
}
I am doing this below, using asp.net mvc, but don't know how to get Shippings as Array [].
Can someone give me some exemplo or anything else... I'll appreciate.
var request = new GetNetRoot() {
SellerId = seller_id,
Amount = orderItens.Amount
Order = new GetNetPagOrder() {
OrderId = order.id.ToString(),
SalesTax = orderItens.Tax,
ProductType = orderItens.ProdType
},
Shippings = new GetNetPagShippings() {
FirstName = "",
PhoneNumber = usr.PhoneNumber,
ShippingAmount = orderItens.AmountShip,
Address = new GetNetPagAddress() {
Street = catEnd.IdEnderecoLogradouroNavigation.IdRuaNavigation.Nome,
Number = catEnd.NumEndereco,
Complement = catEnd.Complemento,
PostalCode = catEnd.IdEnderecoLogradouroNavigation.Cep
}
},
Credit = new GetNetPagCredit() {
Delayed = false,
Authenticated = false
}
};
var requestBody = JsonConvert.SerializeObject(request)
You should initialize Shippings like an array:
Shippings = new[] {
new GetNetPagShippings()
{
FirstName = "",
PhoneNumber = usr.PhoneNumber,
ShippingAmount = orderItens.AmountShip,
Address = new GetNetPagAddress()
{
Street = catEnd.IdEnderecoLogradouroNavigation.IdRuaNavigation.Nome,
Number = catEnd.NumEndereco,
Complement = catEnd.Complemento,
PostalCode = catEnd.IdEnderecoLogradouroNavigation.Cep
}
}
public class GetNetPagamentoRoot
{
...
public GetNetPagShippings[] Shippings { get; set; }
}
You can use array initializer syntax. Simplistic example would be array of int:
int[] myArray = new [] { 1, 2, 3 }
In your code Shippings should be initialized as an array.
var request = new GetNetRoot()
{
SellerId = seller_id,
Amount = orderItens.Amount
Order = new GetNetPagOrder()
{
OrderId = order.id.ToString(),
SalesTax = orderItens.Tax,
ProductType = orderItens.ProdType
},
// Array initializer with 2 elements.
Shippings = new[] {
new GetNetPagShippings()
{
FirstName = "",
PhoneNumber = usr.PhoneNumber,
ShippingAmount = orderItens.AmountShip,
Address = new GetNetPagAddress()
{
Street = catEnd.IdEnderecoLogradouroNavigation.IdRuaNavigation.Nome,
Number = catEnd.NumEndereco,
Complement = catEnd.Complemento,
PostalCode = catEnd.IdEnderecoLogradouroNavigation.Cep
}
},
new GetNetPagShippings()
{
FirstName = "",
PhoneNumber = usr.PhoneNumber,
ShippingAmount = orderItens.AmountShip,
Address = new GetNetPagAddress()
{
Street = catEnd.IdEnderecoLogradouroNavigation.IdRuaNavigation.Nome,
Number = catEnd.NumEndereco,
Complement = catEnd.Complemento,
PostalCode = catEnd.IdEnderecoLogradouroNavigation.Cep
}
}
},
Credit = new GetNetPagCredit()
{
Delayed = false,
Authenticated = false
}
};
var requestBody = JsonConvert.SerializeObject(request);
Your GetNetRoot outer class needs to define the "Shippings" property as a list or array of the GetNetPagShippings class as opposed to a single instance. When you serialize it to JSON, it will be represented as a JSON array of the object.
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var myClassInstance = new MyOuterClass()
{
OuterProperty = "Outer Property",
MyInnerClassList = new List<MyInnerClass>()
{
new MyInnerClass()
{
InnerProperty = "Inner Property Item 1"
},
new MyInnerClass()
{
InnerProperty = "Inner Property Item 2"
}
}
};
string json = JsonConvert.SerializeObject(myClassInstance);
Console.WriteLine(json);
}
}
public class MyOuterClass
{
public string OuterProperty { get; set; }
public List<MyInnerClass> MyInnerClassList { get; set; }
}
public class MyInnerClass
{
public string InnerProperty { get; set; }
}
}
I have a data definition
I Deserialize JSON to this object
#return is JSON
JsonConvert.DeserializeObject<List<Dictionary<Object, Object>>>(utils.RemoveJsonOuterClass("GetTable", JsonConvert.DeserializeObject(#return).ToString()));
olist = [
[{
"item": 1
"Name "One"
}],
[{
"item": 2
"Name "Two"
}],
[{
"item": 1
"Name "One Two"
}]
];
This is a List<Dictionary<Object, Object>>
I need to find all of the items where "item" == 1.
Can I Use Linq? or is there any other way while using a large amount of data?
First: Your json is not correct fix that.
A colon should be present between Name and value.
A comma should be present after item value
and then change your code as below
//Create a class matching response object
public class ResponseItem
{
[JsonProperty("item")]
public int Item { get; set; }
public string Name { get; set; }
}
var responseJson = utils.RemoveJsonOuterClass("GetTable",
JsonConvert.DeserializeObject(#return).ToString();
var responseData = Newtonsoft.Json.JsonConvert.DeserializeObject<List<List<ResponseItem, ResponseItem>>>(responseJson);
Then use foreach with Where and apply condition
foreach (var responseObject in responseData.Where(x=>x.First().Item.Equals(1)))
{
}
Where is deferred execution and on each loop, it returns an object.
Here is the screenshot of my local execution.
Don't know if u're right with the object type. But the task is easy to solve:
static void Main(string[] args)
{
// Build the object
List<Dictionary<int, TestObject>> list = new List<Dictionary<int, TestObject>>();
// fill it with dictionaries
list.Add(new List<TestObject>()
{
new TestObject(){ Id = 1, Name = "One" },
new TestObject() { Id = 2, Name = "Two" },
new TestObject() { Id = 3, Name = "Three" }
}.ToDictionary(d => d.Id));
list.Add(new List<TestObject>()
{
new TestObject() { Id = 2, Name = "Two" },
new TestObject() { Id = 3, Name = "Three" }
}.ToDictionary(d => d.Id));
list.Add(new List<TestObject>()
{
new TestObject(){ Id = 1, Name = "One" },
new TestObject() { Id = 2, Name = "Two" }
}.ToDictionary(d => d.Id));
// Let's build a single list to work with
IEnumerable<TestObject> completeList = list.SelectMany(s => s.Values);
// aaaand filter it
IEnumerable<TestObject> filteredList = completeList.Where(l => l.Id == 1);
}
public class TestObject
{
public int Id { get; set; }
public string Name { get; set; }
}
Most part is initialization ;-)
If I have objects, lets call them Group that has list of some other objects I will call it Brand, and this object has a list of objects called Model.
Is there a way to get only list of Models using MongoDb c# driver.
I tried using SelectMany multiple times but with no success. If I put more than one SelectMany I always get an empty list.
Code should be self-explanatory.
At the end is comment that explains what confuses me.
class Group
{
[BsonId(IdGenerator = typeof(GuidGenerator))]
public Guid ID { get; set; }
public string Name { get; set; }
public List<Brand> Brands { get; set; }
}
class Brand
{
public string Name { get; set; }
public List<Model> Models { get; set; }
}
class Model
{
public string Name { get; set; }
public int Produced { get; set; }
}
class Program
{
static void Main(string[] args)
{
MongoClient client = new MongoClient("mongodb://127.0.0.1:32768");
var db = client.GetDatabase("test");
var collection = db.GetCollection<Group>("groups");
var fca = new Group { Name = "FCA" };
var alfaRomeo = new Brand { Name = "Alfra Romeo" };
var jeep = new Brand { Name = "Jeep" };
var ferrari = new Brand { Name = "Ferrari"};
var laFerrari = new Model { Name = "LaFerrari", Produced = 4 };
var wrangler = new Model { Name = "Wrangler", Produced = 3 };
var compass = new Model { Name = "Compass", Produced = 8 };
var giulietta = new Model { Name = "Giulietta", Produced = 7 };
var giulia = new Model { Name = "Giulia", Produced = 8 };
var _4c = new Model { Name = "4C", Produced = 6 };
fca.Brands = new List<Brand> { ferrari, alfaRomeo, jeep };
ferrari.Models = new List<Model> { laFerrari };
jeep.Models = new List<Model> { wrangler, compass };
alfaRomeo.Models = new List<Model> { giulietta, giulia, _4c };
collection.InsertOne(fca);
Console.WriteLine("press enter to continue");
Console.ReadLine();
var models = collection.AsQueryable().SelectMany(g => g.Brands).SelectMany(b => b.Models).ToList();
Console.WriteLine(models.Count); //returns 0 I expected 6
Console.ReadLine();
}
}
Try
var models = collection.AsQueryable()
.SelectMany(g => g.Brands)
.Select(y => y.Models)
.SelectMany(x=> x);
Console.WriteLine(models.Count());
Working output (with extra Select())
aggregate([{
"$unwind": "$Brands"
}, {
"$project": {
"Brands": "$Brands",
"_id": 0
}
}, {
"$project": {
"Models": "$Brands.Models",
"_id": 0
}
}, {
"$unwind": "$Models"
}, {
"$project": {
"Models": "$Models",
"_id": 0
}
}])
OP Output without extra Select()
aggregate([{
"$unwind": "$Brands"
}, {
"$project": {
"Brands": "$Brands",
"_id": 0
}
}, {
"$unwind": "$Models"
}, {
"$project": {
"Models": "$Models",
"_id": 0
}
}])
I have a situation where I need to format json data into below .
[WebMethod]
public static string ConvertDatadttoString(string appName)
{
var sample = new List<SampleClass>
{
new SampleClass()
{
columns = new List<SampleItem>()
{
new SampleItem() {title = "NAME" },
new SampleItem() {title = "COUNTY" },
},
data = new List<List<string>>()
{
new List<string> { "John Doe", "Fresno" },
new List<string> { "Billy", "Fresno" },
new List<string> { "Tom", "Kern" },
new List<string> { "King Smith", "Kings" },
}
}
};
var serializer = new JavaScriptSerializer();
var json = serializer.Serialize(sample);
return json;
}
public class SampleClass
{
public IEnumerable<SampleItem> columns { get; set; }
public IEnumerable<IEnumerable<string>> data { get; set; }
}
public class SampleItem
{
public string title { get; set; }
}
The above code is giving the correct json data for me, but I need to do some modifications in the code so that it can intake data from my source.First of all new SampleItem() {title = "NAME" }, needs to be populated from stringarray which is like
string columnNames = "Name,County";
string[] arrcolumnNames = columnNames.Split(',');
and secondly,new List<string> { "John Doe", "Fresno" }, needs to be populated from .net DataTable. How to do it.
I tried to add for loop and add the values from string array:
for(int i = 0; i <= arrcolumnNames.Length; i++)
{
new SampleItem() { title = arrcolumnNames[i] }
}
but I'm getting an error.
Try this
public static string ConvertDatadttoString(string appName = "")
{
var columnNames = "Name,County";
var employees = CreateEmployeesTable();
var sample = new List<SampleClass>
{
new SampleClass()
{
columns = columnNames.Split(',').Select(x=> new SampleItem
{
title = x
}),
data = employees.AsEnumerable().Select(row=> new List<string>
{
row.Field<string>("EmployeeName"),
row.Field<string>("Company")
})
}
};
var serializer = new JavaScriptSerializer();
var json = serializer.Serialize(sample);
return json;
}
The private method CreateEmployeesTable
private DataTable CreateEmployeesTable()
{
var table = new DataTable()
{
Columns = { "EmployeeName", "Company" },
TableName = "Employees"
};
table.Rows.Add("John Doe", "Fresno");
table.Rows.Add("Billy", "Fresno");
table.Rows.Add("Tom", "Kern");
table.Rows.Add("King Smith", "Kings");
return table;
}
Update
DataRowExtensions.Field Method has five overload.
The integer overload that accepts an integer (index). If you want to get the first column the index will be 0. So call it like row.Field<string>(0)