Not able to conver json to dataset, datatable - json

I am writing a small tool to convert json to csv. First I try to convert json to Dataset or Datatable but failing.
The Json string is:
{
"id1": {
"id": "id11",
"cards": {
"1": {
"id": "test11",
"fingerprint": "test11",
"last4": "test11",
"exp_month": 7,
"exp_year": 2019,
"brand": "test11"
},
"0": {
"id": "test12",
"fingerprint": "test12",
"last4": "test12",
"exp_month": 7,
"exp_year": 2020,
"brand": "Visa"
},
"2": {
"id": "test13",
"fingerprint": "test13",
"last4": "test13",
"exp_month": 8,
"exp_year": 2020,
"brand": "Visa"
}
}
},
"id2": {
"id": "id21",
"cards": {
"1": {
"id": "test21",
"fingerprint": "test21",
"last4": "test21",
"exp_month": 7,
"exp_year": 2019,
"brand": "MC"
},
"0": {
"id": "test22",
"fingerprint": "test22",
"last4": "test5",
"exp_month": 2,
"exp_year": 2020,
"brand": "Visa"
}
}
}
}
I tried
DataSet ds = JObject.Parse(jsonContent)["root"].ToObject<DataSet>();
DataTable dt = JsonConvert.DeserializeObject<DataTable>(jsonContent);
But it does not work. Gives this error with first one:
An unhandled exception of type 'System.NullReferenceException' occurred in JsonToCsv.exe
Additional information: Object reference not set to an instance of an object.
This error with second one:
An unhandled exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll
Additional information: Unexpected JSON token when reading DataTable. Expected StartArray, got StartObject. Path '', line 1, position 1.
Any suggestion would be appreciated

I managed to parse json into a list and then converted list to csv. the code to parse json to list is as follows:
public class Card
{
public string ActId { get; set; }
public string CustId { get; set; }
public string Id { get; set; }
public string Fingerprint { get; set; }
public string Last4 { get; set; }
public int Exp_month { get; set; }
public int Exp_year { get; set; }
public string Brand { get; set; }
}
public static List<Card> JsonToCSV(string JsonContent)
{
var ds = JObject.Parse(JsonContent);
var cards = new List<Card>();
foreach (var item in ds)
{
var crds= JObject.Parse(JsonConvert.DeserializeObject(item.Value["cards"].ToString()).ToString());
foreach (var crd in crds)
{
var card =JsonConvert.DeserializeObject<Card>(crd.Value.ToString());
card.ActId= item.Key;
card.CustId= item.Value["id"].ToString();
cards.Add(card);
}
}
return cards;
}

Related

stream writer is not writing to JSON file in webapi

Im trying to write data in a JSON file using webapi but stream writer is not writing data to the file.
JSON File :
{
"Students": [
{
"id": 1,
"name": "Ravi",
"department": "IT"
},
{
"id": 2,
"name": "Raj",
"department": "hr"
},
{
"id": 3,
"name": "avi",
"department": "it"
},
{
"id": 4,
"name": "rome",
"department": "HR"
},
{
"id":5,
"name": "virat",
"department": "HR"
},
{
"id":6 ,
"name": "Tushar",
"department": "RM"
}
]
}
Class
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public string Department { get; set; }
}
public class Students
{
public List<Student> students { get; set; }
}
Api controller: [HttpPost] method for writing data to the json file.
[Route("api/[controller]")]
[ApiController]
public class StudentsController : ControllerBase
{
[HttpPost]
public IActionResult Add(Students _Student)
{
using (var fs = new FileStream("C:/Users/tanmay_pawar/source/repos/CRUDAPI/CRUDAPI/people.json", FileMode.Append))
using (var sw = new StreamWriter(fs))
{
sw.WriteLine(_Student);
}
}
The data recieved in by _Student is not getting added to the json file.
try this
public IActionResult Add(Students _Student)
{
if(_Student==null || _Student.students==null) return null;
var filePath = #"C:\Users\....\..json";
var json = File.ReadAllText(filePath);
Students students = JsonConvert.DeserializeObject<Students>(json);
students.students.AddRange(_Student.students);
json=JsonConvert.SerializeObject(students);
File.WriteAllText(filePath, json);
}
Try the code like below:
[HttpPost]
public IActionResult Add(Students _Student)
{
string jsonresult = JsonConvert.SerializeObject(_Student);
string path = #"C:\c\people.json";
using(var tw=new StreamWriter(path,true))
{
tw.WriteLine(jsonresult.ToString());
tw.Close();
}
return Ok();
}
result:
Update more picture, add data inside the existing JSON file.

Cannot deserialize the current JSON object .Net Core 5

I have a .Net Core 5 solution that is largely he same as another previous, working solution. In both the controllers are .Net Core 5. In the previous, working one, the services, models and view models are in a 4.7 project. Most of the new solution is working, except for one controller that takes a nested (master/detail) JSON sent in the body of the request. The service is set up to deserialize the JSON into a dataset. The JSON shows as valid in the jsonlint.com validator.
However, I keep getting this error in Postman:
"Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IList`1[Sage100_API.ViewModels.APInvoiceReq]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.\r\nTo fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.\r\nPath 'APInvoiceRequest', line 2, position 21."
[JsonObjectAttribute] is already in place in the viewmodels involved.
The error occurs when stepping off the final curly bracket in this code in the controller:
public APInvoiceResponseController(IAPInvoiceService apInvoiceService, IOptions<AppSettingsModel> app)
{
APInvoiceService = apInvoiceService;
AppSettings = app;
}
What is different between core 5 and 4.7 in deserializing in NewtonSoft JSON?
edit: adding JSON and code
JSON:
{
"APInvoices": {
"APInvoice": [
{
"APDivisionNo": "00",
"APVendorNo": "0000006",
"PayeeTermsCd": "00",
"HoldPayment": "N",
"SeparateCheck": "N",
"InvoiceNo": "12345",
"InvoiceDate": "2022-04-06",
"BatchNmbr": "490",
"TotalAmount": 150,
"APInvoiceDetails": {
"APInvoiceDetail": [
{
"InvoiceNo": "12345",
"Line": "1",
"Amount": "25.7500",
"GLAcctID": "5000-00-10",
"Comment": "line 1 comment",
"BatchNmbr": "490"
},
{
"InvoiceNo": "12345",
"Line": "2",
"Amount": "75.2500",
"GLAcctID": "5000-00-10",
"Comment": "line 2 comment",
"BatchNmbr": "490"
},
{
"InvoiceNo": "12345",
"Line": "3",
"Amount": "49.00",
"GLAcctID": "5000-00-10",
"Comment": "line 3 comment",
"BatchNmbr": "490"
}
]
},
{
"APDivisionNo": "00",
"APVendorNo": "0000006",
"PayeeTermsCd": "00",
"HoldPayment": "N",
"SeparateCheck": "N",
"InvoiceNo": "12346",
"InvoiceDate": "2022-04-06",
"BatchNmbr": "490",
"TotalAmount": 150,
"APInvoiceDetails": {
"APInvoiceDetail": [
{
"InvoiceNo": "12345",
"Line": "1",
"Amount": "25.7500",
"GLAcctID": "5000-00-10",
"Comment": "line 1 comment",
"BatchNmbr": "490"
},
{
"InvoiceNo": "12345",
"Line": "2",
"Amount": "75.2500",
"GLAcctID": "5000-00-10",
"Comment": "line 2 comment",
"BatchNmbr": "490"
},
{
"InvoiceNo": "12345",
"Line": "3",
"Amount": "49.00",
"GLAcctID": "5000-00-10",
"Comment": "line 3 comment",
"BatchNmbr": "490"
}
]
}
}
]
}
}
Controller:
{
[ApiController]
public class APInvoiceResponseController : ControllerBase
{
//private readonly S100Entities Context;
private readonly IAPInvoiceService APInvoiceService;
private readonly IOptions<AppSettingsModel> AppSettings;
public APInvoiceResponseController(IAPInvoiceService apInvoiceService, IOptions<AppSettingsModel> app)
{
APInvoiceService = apInvoiceService;
AppSettings = app;
}
[HttpPost]
[Route("apinvoice")]
public async Task<IActionResult> Basic([FromBody] IList<APInvoiceReq> apInvoice)
{
try
{
var APInvoices = await APInvoiceService.PostAPInvoices(apInvoice);
try
{
if (apInvoice == null)
{
return BadRequest("Missing transaction data.");
}
if (APInvoices == null)
{
return NotFound();
}
return Ok(APInvoices);
}
catch (System.Exception e)
{
Serilog.Log.Error("Error in APInvoices", e);
APInvoices.SuccessErrorWarningResult.AddError(666, e.ToString());
return Ok(APInvoices);
}
}
catch (System.Exception e)
{
Serilog.Log.Error("Error in APInvoices", e);
return BadRequest();
}
}
}
}
APInvoiceReq class:
{
[JsonObjectAttribute]
[JsonArray]
[Serializable]
public class APInvoiceReq : S100Object<APInvoiceReq>
{
public string APDivisionNo { get; set; }
public string APVendorNo { get; set; }
public string PayeeTermsCd { get; set; }
public string HoldPayment { get; set; }
public string SeparateCheck { get; set; }
public string InvoiceNo { get; set; }
public DateTime InvoiceDate { get; set; }
public string InvoiceComment { get; set; }
public int BatchNmbr { get; set; } //UDF_BATCH_NO
public decimal TotalAmount { get; set; }
public IEnumerable<APInvoiceDetail> APInvoiceDetails { get; set; }
}
}

How to extract only part of the JSON and de-serialize it in .netcore

I have .net core application , where an API is called through HTTPClient.
The response for that API in JSON format is as follows:
{
"ID": 25,
"Customer": "CustomerName",
"total": 100,
"details": [
{
"ItemId": "Item1",
"ItemName": "Name1",
"Price": "10"
},
{
"ItemId": "Item2",
"ItemName": "Name2",
"Price": "50"
},
{
"ItemId": "Item3",
"ItemName": "Name3",
"Price": "40"
}
]
}
I get this response from -- > var response = client.GetAsync(ApiPath).Result;
Now from the response variable I need details only for details like :
{
{
"ItemId": "Item1",
"Price": "10"
},
{
"ItemId": "Item2",
"Price": "50"
},
{
"ItemId": "Item3",
"Price": "40"
}
}
I have a DTO class like this :
public class ItemDetails
{
public string ItemId { get; set; }
public string Price { get; set; }
}
Can anyone help in extracting the details according to the DTO class from the main variable "response".
Many thanks!
Try this if you are using newtonsoft
var token = JObject.Parse(response);//load
var detailsToken = token.SelectToken("details");//select
var itemDetails = detailsToken.ToObject<ItemDetails[]>(); //cast to array
Only the properties that exist on ItemDetails will be mapped
You can deserialize the response into an object and take whatever you like from it.
Use the built-in JSON library in .net-core as following
using System.Text.Json;
using System.Text.Json.Serialization;
then make a Response classes to contain the Response values
public class ResponseObject
{
public int ID { get; set; }
public string Customer { get; set; }
[JsonPropertyName("total")]
public int Total { get; set; }
[JsonPropertyName("details")]
public ItemDetails[] Details { get; set; }
}
public class ItemDetails
{
public string ItemId { get; set; }
public string ItemName { get; set; }
public string Price { get; set; }
}
finally, deserialize and extract whatever you like as following
var o = JsonSerializer.Deserialize<ResponseObject>(response);
ItemDetails[] itemDetails= o.Details;

Json.net append json file

I have the following code which uses Json.net:
class HistorianRecord
{
public string tagname { get; set; }
public string engunits { get; set; }
public string value { get; set; }
public string quality { get; set; }
public DateTime timestamp { get; set; }
}
private static void createJSONFile(DataTable dt)
{
var HistorianData = new List<HistorianRecord>();
foreach(DataRow row in dt.Rows)
{
HistorianData.Add(new HistorianRecord()
{
tagname = row["tagname"].ToString(),
engunits = row["engunits"].ToString(),
value = row["value"].ToString(),
quality = row["quality"].ToString(),
timestamp = DateTime.Parse(row["timestamp"].ToString())
});
}
var serializer = new JavaScriptSerializer();
var serializedResult = serializer.Serialize(HistorianData);
var deserializedResult = serializer.Deserialize<List<HistorianRecord>>(serializedResult);
File.WriteAllText(folderPath + fileName, JsonConvert.SerializeObject(deserializedResult));
}
Which produces the following JSON file, which I have shortened for this post as the are > 1000 rows in the datatable:
[
{
"tagname": "mytag1",
"engunits": "",
"value": "2",
"quality": "Good NonSpecific",
"timestamp": "2018-12-13T10:45:05Z"
},
{
"tagname": "myTag2",
"engunits": "",
"value": "0",
"quality": "Good NonSpecific",
"timestamp": "2018-12-13T10:45:00Z"
}
]
I would like to amend my code to so I can add some items at the beginning of the JSON file so it looks more like this:
[
{
"name": "ARandomName",
"content": [
{
"tagname": "mytag1",
"engunits": "",
"value": "2",
"quality": "Good NonSpecific",
"timestamp": "2018-12-13T10:45:05Z"
},
{
"tagname": "myTag2",
"engunits": "",
"value": "0",
"quality": "Good NonSpecific",
"timestamp": "2018-12-13T10:45:00Z"
}
]
}
]
This is so I can create some documents for a test MongoDB installation that I am investigating so all help is appreciated.
You simply can wrap your deserialized list of HistorianRecords in an anonymous object and reserialize it:
var anon = new
{
name = "ARandomName",
content = deserializedResult
};
string newJson = JsonConvert.SerializeObject(anon, Formatting.Indented);
Fiddle: https://dotnetfiddle.net/6kSvxS

Deserialize complex object with Json

How would I deserialize this with JSON.NET. I keep getting a "cannot perform binding on a null reference" exception. Here is the code, and the JSON output below:
var json = client.DownloadString("https://myapp.tpondemand.com/api/v1/UserStories?take=999&include=[Tasks[Id,Name,TimeSpent]]&format=json");
dynamic output = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
string nemo = output.items[1].Id[0];
Console.ReadLine();
{
"Items": [
{
"Id": 395,
"Tasks": {
"Items": []
}
},
{
"Id": 394,
"Tasks": {
"Items": []
}
},
{
"Id": 393,
"Tasks": {
"Items": []
}
},
{
"Id": 336,
"Tasks": {
"Items": []
}
},
}
]
If you know Json format just create datacontracts and deserialize them.
For example
[DataContract]
public class ItemJson
{
[DataMember]
public string Id { get; set; }
[DataMember]
public List<TaskJson> Tasks { get; set; }
}
[DataContract]
public class TaskJson
{
[DataMember]
public List<ItemJson> Items{ get; set; }
}