I am trying to deserialize JSON data to a dataset - c#

I thought JSON was supposed to be easy to use.
I have a C# .NET Windows form program in Visual Studio 2015 being used as a client consuming a Web API 2 remote server with RestSharp as the HTTP client.
the data returned from the API call is in Json format. However, when I try to deserialize the returned Json into a dataset using this statement:
DataSet data = (DataSet)JsonConvert.DeserializeObject(response.Content, (typeof(DataSet))); ,
I get this error:
"Unexpected JSON token while reading DataTable: EndArray".
If I use the text from "response.Content" and validate it here: http://www.jsonlint.com/#, the results says "Valid JSON".
When I use the debugger to view the "response.Content" as Json, it shows the correct records that I am looking for.
I have tried different formats of JsonConvert, such as:
DataSet data = JsonConvert.DeserializeObject<DataSet>(response.Content);
DataTable datat = (DataTable)JsonConvert.DeserializeObject(response.Content, (typeof(DataTable)));
I also tried this:
XmlDocument xd1 = new XmlDocument();
xd1 = (XmlDocument)JsonConvert.DeserializeXmlNode(response.Content, "RootObject");
DataSet dataset = new DataSet();
dataset.ReadXml(new XmlNodeReader(xd1));
which I got from here: http://www.c-sharpcorner.com/blogs/how-to-parse-json-string-to-dataset-in-c-sharp1
That seems to work without giving an error, but the dataset contains four tables ( RootObject, data, CustomerRoles and ShoppingCartitems).
I tried removing three of the tables, but there are constraints and foreignkeys that I don't know how to remove and it won't allow me to remove the tables until I remove the constraints. If I try to remove the constraints, it gives this error: "Cannot remove unique constraint 'Constraint1'. Remove foreign key constraint 'RootObject_data' first."
Does anybody know how to use the "easy to use", "most popular" JSON format to deserialize my Json data into a dataset and come out with one table of data?
JSON data
{
"success": true,
"data": [{
"Id": 6,
"CustomerGuid": "70b390d8-82d5-4bba-aa68-fc8268a1b1ff",
"UserName": "victoria_victoria#nopCommerce.com",
"Email": "victoria_victoria#nopCommerce.com",
"CustomerRoles": [{
"Id": 3,
"Name": "Registered",
"SystemName": "Registered"
}],
"AdminComment": null,
"IsTaxExempt": false,
"AffiliateId": 0,
"VendorId": 0,
"HasShoppingCartItems": false,
"Active": false,
"Deleted": false,
"IsSystemAccount": false,
"SystemName": null,
"LastIpAddress": null,
"CreatedOnUtc": "\/Date(1472933472393)\/",
"LastLoginDateUtc": null,
"LastActivityDateUtc": "\/Date(1472933472393)\/",
"ExternalAuthenticationRecords": [],
"ShoppingCartItems": []
}, {
"Id": 5,
"CustomerGuid": "eb9e6f24-f362-4c10-942a-366e2919dc11",
"UserName": "brenda_lindgren#nopCommerce.com",
"Email": "brenda_lindgren#nopCommerce.com",
"CustomerRoles": [{
"Id": 3,
"Name": "Registered",
"SystemName": "Registered"
}],
"AdminComment": null,
"IsTaxExempt": false,
"AffiliateId": 0,
"VendorId": 0,
"HasShoppingCartItems": false,
"Active": false,
"Deleted": false,
"IsSystemAccount": false,
"SystemName": null,
"LastIpAddress": null,
"CreatedOnUtc": "\/Date(1472933472363)\/",
"LastLoginDateUtc": null,
"LastActivityDateUtc": "\/Date(1472933472363)\/",
"ExternalAuthenticationRecords": [],
"ShoppingCartItems": []
}, {
"Id": 4,
"CustomerGuid": "9f46dbae-6942-410c-90b8-9b38a0890064",
"UserName": "james_pan#nopCommerce.com",
"Email": "james_pan#nopCommerce.com",
"CustomerRoles": [{
"Id": 3,
"Name": "Registered",
"SystemName": "Registered"
}],
"AdminComment": null,
"IsTaxExempt": false,
"AffiliateId": 0,
"VendorId": 0,
"HasShoppingCartItems": false,
"Active": false,
"Deleted": false,
"IsSystemAccount": false,
"SystemName": null,
"LastIpAddress": null,
"CreatedOnUtc": "\/Date(1472933472317)\/",
"LastLoginDateUtc": null,
"LastActivityDateUtc": "\/Date(1472933472317)\/",
"ExternalAuthenticationRecords": [],
"ShoppingCartItems": []
}, {
"Id": 3,
"CustomerGuid": "6277386b-13ee-427b-9cfe-4ebfa487c340",
"UserName": "arthur_holmes#nopCommerce.com",
"Email": "arthur_holmes#nopCommerce.com",
"CustomerRoles": [{
"Id": 3,
"Name": "Registered",
"SystemName": "Registered"
}],
"AdminComment": null,
"IsTaxExempt": false,
"AffiliateId": 0,
"VendorId": 0,
"HasShoppingCartItems": false,
"Active": false,
"Deleted": false,
"IsSystemAccount": false,
"SystemName": null,
"LastIpAddress": null,
"CreatedOnUtc": "\/Date(1472933472253)\/",
"LastLoginDateUtc": null,
"LastActivityDateUtc": "\/Date(1472933472253)\/",
"ExternalAuthenticationRecords": [],
"ShoppingCartItems": []
}, {
"Id": 2,
"CustomerGuid": "241f45f1-b38c-4e22-8c5a-743fa3276620",
"UserName": "steve_gates#nopCommerce.com",
"Email": "steve_gates#nopCommerce.com",
"CustomerRoles": [{
"Id": 3,
"Name": "Registered",
"SystemName": "Registered"
}],
"AdminComment": null,
"IsTaxExempt": false,
"AffiliateId": 0,
"VendorId": 0,
"HasShoppingCartItems": false,
"Active": false,
"Deleted": false,
"IsSystemAccount": false,
"SystemName": null,
"LastIpAddress": null,
"CreatedOnUtc": "\/Date(1472933472207)\/",
"LastLoginDateUtc": null,
"LastActivityDateUtc": "\/Date(1472933472207)\/",
"ExternalAuthenticationRecords": [],
"ShoppingCartItems": []
}, {
"Id": 1,
"CustomerGuid": "a940dc03-5f52-47d2-9391-8597b3b31cf2",
"UserName": "tony#lakesideos.com",
"Email": "tony#lakesideos.com",
"CustomerRoles": [{
"Id": 1,
"Name": "Administrators",
"SystemName": "Administrators"
}, {
"Id": 2,
"Name": "Forum Moderators",
"SystemName": "ForumModerators"
}, {
"Id": 3,
"Name": "Registered",
"SystemName": "Registered"
}],
"AdminComment": null,
"IsTaxExempt": false,
"AffiliateId": 0,
"VendorId": 0,
"HasShoppingCartItems": true,
"Active": true,
"Deleted": false,
"IsSystemAccount": false,
"SystemName": null,
"LastIpAddress": "71.185.255.7",
"CreatedOnUtc": "\/Date(1472933470783)\/",
"LastLoginDateUtc": "\/Date(1477522483903)\/",
"LastActivityDateUtc": "\/Date(1477523996553)\/",
"ExternalAuthenticationRecords": [],
"ShoppingCartItems": [{
"Id": 1,
"StoreId": 1,
"ShoppingCartTypeId": 1,
"CustomerId": 1,
"ProductId": 18,
"AttributesXml": null,
"CustomerEnteredPrice": 0.0000,
"Quantity": 1,
"CreatedOnUtc": "\/Date(1473801903447)\/",
"UpdatedOnUtc": "\/Date(1473803336207)\/",
"IsFreeShipping": false,
"IsShipEnabled": true,
"AdditionalShippingCharge": 0.0000,
"IsTaxExempt": false
}]
}]
}

Here's a brief overview of what you need to do.
Taking from NewtonSoft - Deserialize Object example
Snippet of your data
{
"Id": 1,
"CustomerGuid": "a940dc03-5f52-47d2-9391-8597b3b31cf2",
"UserName": "tony#lakesideos.com",
"Email": "tony#lakesideos.com"
This is a Customer object. It needs it's own C# model class.
public class Customer {
int id;
string guid;
string username;
string email;
// etc...
// getters and setters...
}
This is stored in a list of data
"data": [ { ... }, { ... } ]
You need another Object to hold a list of those objects plus a boolean success value. Let's call this one Response.
{
"success": true,
"data": [{
That class starts with
public class Response {
bool success;
IList<Customer> data;
Then, you need other lists and object classes for something like this
"CustomerRoles": [{
"Id": 3,
"Name": "Registered",
"SystemName": "Registered"
}],
Once you've modeled the entire domain of classes, you should be able to have
Response res = JsonConvert.DeserializeObject<Response>(json);
Since you seem to have already tried that, and are getting an error about the END_ARRAY character, something within your DataSet class is not correctly mapped to a List
And then get res.data to access the list of data, then you can loop over those Customer objects to build your Dataset / table objects, I assume to display your data in some list of the GUI

Try starting from Response.Data instead of Response.Content, that will get you one layer in to expose the actual data to deserialize.
For example:
var response = _requestProcessor.Process<Request, Response>(
new Request(id)).dataList;
return new JsonNetResult() { Data = response, JsonRequestBehavior= JsonRequestBehavior.AllowGet };
Whatever the Request object is, it has an object that holds the responses' data in it; that is the actual item to deserialize.
Perhaps what you need to do is what Cricket_007 suggests, and make a class to encapsulate the Success object returned in the JSON, then deserialize to one Success object and a Data object, which is a list of the objects you're trying to get to.
The steps you need to follow are:
Convert the whole JSON string to an object that consists of the two objects within, Success and Data.
JSONObject content = new JSONObject(Response.Content); perhaps, this is untested.
From that object, deserialize just the Data object within it.
content.data -or- content["data"]
or some such should get you to the parts you want to work with.

Related

Solr .Net Facet Term for obtaining numBuckets

Trying to implement with the following Facet Term which works when querying through postman but I cannot find any equivalent in Solr.NET as there are not facet term queries. I can see by field, range, and pivots. I would need to get the numBuckets and I do not see how this can me achieved in with the Solr.NET libraries.
Postman body example.
{
"query": "*:*",
"fields": [
"user_id"
],
"filter": [
"",
],
"facet": {
"user_id": {
"mincount": 1,
"numBuckets": true,
"allBuckets": false,
"offset": 0,
"type": "terms",
"field": "user_id",
"limit": 1
}
},
"params": {
"echoParams": "none"
},
"limit": 100,
"offset": 0,
"sort": "ismail_bius asc,createdon_zius desc"
}
I have tried to pass it in the ExtraParams property of the query options but no luck on it.
Thanks.

How to skip fields with default values in JSON response in HotChocolate/GraphQl

I want to remove fields from output JSON with default values (0, false) to reduce size of response, but can't find a way how to do it in HotChocolate/GraphQl.
I didn't find a settings to control it (JsonFormatter), "Optional" also not for this purposes, and there is not options to do it via query syntax.
After query to graphQl I receive a long list, with many default values in JSON output, simple example, pay attention to "sortOrder" and "isDeleted":
"values": [{
"id": 448,
"name": "Dr.",
"isDeleted": false,
"sortOrder": 0
}, {
"id": 449,
"name": "Mr.",
"isDeleted": true,
"sortOrder": 0
}, {
"id": 450,
"name": "Mrs.",
"isDeleted": false,
"sortOrder": 1
}]
Expecting result:
"values": [{
"id": 448,
"name": "Dr.",
}, {
"id": 449,
"name": "Mr.",
"isDeleted": true,
}, {
"id": 450,
"name": "Mrs.",
"sortOrder": 1
}]
Query:
getLookups(withDeleted: true) {
id
name
isDeleted
values {
id
name
isDeleted
sortOrder
}
}
Type description:
descriptor.BindFields(BindingBehavior.Explicit);
descriptor.Interface<ILookupValueType>();
descriptor.Field(f => f.Id).Type<NonNullType<IntType>>();
descriptor.Field(f => f.Name).Type<StringType>();
descriptor.Field(f => f.Image).Type<StringType>();
descriptor.Field(f => f.IsDeleted).Type<BooleanType>();
descriptor.Field(f => f.IsDefault).Type<BooleanType>();
descriptor.Field(f => f.SortOrder).Type<IntType>();
P.S. Please, don't offer pagination, it is not what I need.
And thank you for your help.

Azure Cognitive Search - match exact phrase for some fields

I have different fields in my Azure Cognitive Search but let me show you some with which I have problems.
{
"name": "Name",
"type": "Edm.String",
"searchable": true,
"filterable": false,
"retrievable": true,
"sortable": true,
"facetable": false,
"key": false,
"indexAnalyzer": null,
"searchAnalyzer": null,
"analyzer": "standard.lucene",
"synonymMaps": []
}
and
{
"name": "Code",
"type": "Edm.String",
"searchable": true,
"filterable": false,
"retrievable": true,
"sortable": false,
"facetable": false,
"key": false,
"indexAnalyzer": null,
"searchAnalyzer": null,
"analyzer": "keyword",
"synonymMaps": []
}
As you can see above, for Name I set analyzer standard.lucene (I have language-specific for other fields like NameEn) and keyword analyzer for Code field.
For example, when I search by 1-1 it looks for 1 instead of 1-1. I try with double quotes but it seems I also don't work ("1-1").
The issue is that as a result I get Name with the number 1 instead of Code which have 1-1.
Do you have any idea how can I do it? I suppose I should search by the whole phrase like: "1-1" rest part of the query.
When you send query it is analyzed by analyzers of all searchable fields and then tokenized query (different for each field) will be executed against all of them.
You can send queries to analyze endpoint to debug how each analyzer is working with your query -
https://serviceName.search.windows.net/indexes/index-name/analyze?api-version=2020-06-30
In your case:
{
"text": "1-1",
"analyzer": "standard"
}
returns these tokens for Name field
"tokens": [
{
"token": "1",
"startOffset": 0,
"endOffset": 1,
"position": 0
},
{
"token": "1",
"startOffset": 2,
"endOffset": 3,
"position": 1
}
]
and for Code field
{
"text": "1-1",
"analyzer": "keyword"
}
you get
"tokens": [
{
"token": "1-1",
"startOffset": 0,
"endOffset": 3,
"position": 0
}
]
So with such query you are really looking for documents with
Name=1 | Code=1-1
If you want to search only in selected fields you can specify them using searchFields parameter.

SqlBulkCopy for datatables having inner datatables in c# console application

I have a datatable with 15 columns out of which 2 columns contain inner datatables containing 5 columns each. Is it possible to break hierarchy and add inner datatable columns to main datatable columns?
Or can I seperate those 2 columns from datatable and load them into different sql server table?
Inner datatables are formed by reading JSONArray object with multiple values.
I use following code part to Deserialize JSON into Datatable
var dtset = JsonConvert.DeserializeObject<DataTable>(JSON);
My JSON looks like below,
[{
"cpty": "SG, LP",
"internallegalentity": "ABC, LN",
"createdate": null,
"paymentcurrency": "USD",
"id": 123,
"version": 1,
"revisiondate": "2020-01-31 12:33:39.714",
"amount": -4.25,
"duedate": "2020-01-29",
"asofdate": "2020-02-25",
"isdeleted": false,
"source": "XYZ",
"isprovisional": null,
"isproforma": null,
"items": [{
"id": 123,
"amount": -4.25,
"currency": "USD",
"itemid": 15505,
"quantity": 1600.0,
"unit": "MWh",
"enddate": "2020-02-29",
"startdate": "2020-02-01",
"transactiondate": "2020-01-29",
"description": "Cash",
"price": 1.0
}],
"payments": [{
"createdate": "2020-02-12T00:00:00Z",
"transactiondate": "2020-02-11T12:00:00Z",
"paymentmethod": "Check",
"amount": 100.0,
"paymentcurrency": "USD",
"id": 123
},
{
"createdate": "2020-02-12T00:00:00Z",
"transactiondate": "2020-02-12T11:30:00Z",
"paymentmethod": "Check",
"amount": 100.0,
"paymentcurrency": "USD",
"id": 123
}
]
},
{
"counterparty": "AU",
"internallegalentity": "xyc, LP",
"createdate": null,
"paymentcurrency": "USD",
"id": 125,
"version": 1,
"revisiondate": "2020-01-31 12:33:39.922",
"amount": -5120.0,
"duedate": "2020-01-30",
"asofdate": "2020-02-25",
"isdeleted": false,
"source": "XYZ",
"isprovisional": null,
"isproforma": null,
"items": [{
"id": 125,
"amount": -1280.0,
"currency": "USD",
"itemid": 15508,
"quantity": 64000.0,
"unit": "MWh",
"enddate": "2021-02-28",
"startdate": "2021-01-01",
"transactiondate": "2020-01-30",
"description": "Cash",
"price": 1.0
},
{
"id": 125,
"amount": -1280.0,
"currency": "USD",
"itemid": 15507,
"quantity": 64000.0,
"unit": "MWh",
"enddate": "2021-02-28",
"startdate": "2021-01-01",
"transactiondate": "2020-01-30",
"description": "Cash",
"price": 1.0
}
]
}
]
Is there any way to read above JSON in more approprate way?
I'm assuming the real struggle you're having is not so much about the bulk copy aspect per se, but about flattening out the datatables. So aside from some simple code at the end, I'll really focus on that problem.
By the way, this is how you represent json in c# (fill in the elipsies of course):
static string json = #"
[
{
""cpty"": ""SG, LP"",
""internallegalentity"": ""ABC, LN"",
""createdate"": null,
""paymentcurrency"": ""USD"",
""id"": 123,
""version"": 1,
...
},
...
]";
First, create three DataTable variables. The first is your parsed json data, the other two are empty ones to receive your items and payments data:
DataTable jsonTable = JsonConvert.DeserializeObject<DataTable>(json);
DataTable items = null;
DataTable payments = null;
Next, loop through your parsed json data and extract your nested datatables into their variable counterparts. On the first pass, you'll want to copy the tables into their respective variables. On subsequent passes, you'll want to merge the tables into the variables. And be careful for the DBNull result in your payments field.
foreach (DataRow row in jsonTable.Rows) {
// get the inner "items"
var jsonItems = (DataTable)row["items"];
if (items == null)
items = jsonItems.Copy(); // first pass
else
items.Merge(jsonItems); // subsequent passes
// there is a null payments record, ignore it
if (row["payments"] == DBNull.Value)
continue;
// get the inner payments
var jsonPayments = (DataTable)(row["payments"]);
if (payments == null)
payments = jsonPayments.Copy(); // first not null pass
else
payments.Merge(jsonPayments); // subsequent passes
}
Now that you have the items and payments tables, delete those fields from your originally parsed table:
jsonTable.Columns.Remove("items");
jsonTable.Columns.Remove("payments");
You are now ready to bulk copy as appropriate. The following untested code assumes you already have existing tables with columns in the same order as your datatable representations.
using (var bulkcopy = new SqlBulkCopy("connection string")) {
bulkcopy.DestinationTableName = "main";
bulkcopy.WriteToServer(jsonTable);
bulkcopy.DestinationTableName = "items";
bulkcopy.WriteToServer(items);
bulkcopy.DestinationTableName = "payments";
bulkcopy.WriteToServer(payments);
}

C# : asp.net 3.5 : Deserialize JSON - json string or object?

i have posted how to deserialize a json in c# but this is my question:
i got this json string :
data = #"[{""ShiftID"":""2"",""EmpName"":""dsdsfs""},{""ShiftID"":""4"",""EmpName"":""dsdsfd""}]";
and my code can deserialize it perfectly but well, if i receive this type :
data = #"[{
"Q6Option": null,
"Q5Comments": "",
"EndDate": "01/17/2012 12:57",
"Q4Comments": "",
"Active": 1,
"Q3Comments": "",
"Q8Option": null,
"Q2Comments": "",
"StartDate": "01/17/2012 12:57",
"Q3Option": null,
"Q5Option": null,
"Q1Comments": "",
"Q2Option": null,
"Station": "B1",
"Q7Option": null,
"SyncDate": null,
"ID": 1,
"Q8Comments": "",
"Q4Option": null,
"ShiftID": 1,
"EmpName": "CSM FName",
"Q1Option": null,
"Q7Comments": "",
"SyncStatus": 0,
"Q6Comments": "",
"EmpID": "111",
"createdAt": "2012-01-17T20:58:17.956Z",
"updatedAt": "2012-01-17T20:58:17.956Z",
"objectId": "XERFM5KrGv"
}]"
it doesnt work because of there is missing ""..
Well if you have an idea , thanks!
You can use the JavaScriptSerializer class that are supported from .NET framework 3.5
Reference link:
http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx
Sample link:
http://msdn.microsoft.com/en-us/library/bb412170.aspx
There are some sample json texts that are same as your issue:
{"__type":"Shape:#MyApp.Shapes","x":50,"y":70}

Categories

Resources