Serialization of nested json no definition of fields - c#

I'm trying to serializa a json. I have created a helper class for it yet it claims that SerializeJsonBody has no definition of the fields I need to fill. When I use the deeper classes the definition is ok yet I won't create the full json.
My end result should look like this:
{"invoiceHash": { "hashSHA":{ "algorithm": "SHA-256","encoding": "Base64","value": {0}},"fileSize": {1}}, "invoicePayload":{ "type": "plain","invoiceBody": {2}} }
public class SerializeJsonBody
{
public invoiceHash invoiceHash { get; set; }
public invoicePayload invoicePayload { get; set; }
}
public class invoiceHash
{
public hashSHA hashSHA { get; set; }
public string fileSize { get; set; }
}
public class hashSHA
{
public string algorithm { get; set; }
public string encoding { get; set; }
public string value { get; set; }
}
public class invoicePayload
{
public string type { get; set; }
public string invoiceBody { get; set; }
}
SerializeJsonBody body = new SerializeJsonBody
{
algorithm = "SHA-256",
encoding = "Base64",
value = "",
fileSize = "",
type = "plain",
invoiceBody = ""
};
string json = JsonConvert.SerializeObject(body, Formatting.Indented);
Edit. I think I figured it out.. Not sure if the best way yest it works
SerializeJsonBody body = new SerializeJsonBody
{
invoiceHash = new invoiceHash
{
hashSHA = new hashSHA
{
algorithm = "SHA-256",
encoding = "Base64",
value = base64hash
},
fileSize = lenght
},
invoicePayload = new invoicePayload
{
type = "plain",
invoiceBody = base64
}
};
string json = JsonConvert.SerializeObject(body, Formatting.Indented);

There is no method with this signature in the documentation, I strongly recommend that you visit it
Your issue can be solved with JsonSerializerSettings

Related

How can I convert a json string to a json array using Newtonsoft?

I am using this code to read a json file firstSession.json and display it on a label.
var assembly = typeof(ScenarioPage).GetTypeInfo().Assembly;
string jsonFileName = "firstSession.json";
Stream stream = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.{jsonFileName}");
using (var reader = new StreamReader(stream))
{
var json = reader.ReadToEnd(); //json string
var data = JsonConvert.DeserializeObject<SessionModel>(json);
foreach (SessionModel scenario in data)
{
scenarioName.Text = scenario.title;
break;
}
scenarioName.Text = data.title; // scenarioName is the name of the label
}
SessionModel.cs looks like:
public class SessionModel : IEnumerable
{
public int block { get; set; }
public string name { get; set; }
public string title { get; set; }
public int numberMissing { get; set; }
public string word1 { get; set; }
public string word2 { get; set; }
public string statement1 { get; set; }
public string statement2 { get; set; }
public string question { get; set; }
public string positive { get; set; } // positive answer (yes or no)
public string negative { get; set; } // negative answer (yes or no)
public string answer { get; set; } // positive or negative
public string type { get; set; }
public string format { get; set; }
public string immersion { get; set; }
public IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
}
The beginning of my json is:
{
"firstSession": [
{
"block": 1,
"name": "mark",
"title": "mark's house",
"numberMissing": 1,
"word1": "distracted",
"word2": "None",
"statement1": "string 1",
"statement2": "None",
"question": "question",
"positive": "No",
"negative": "Yes",
"answer": "Positive",
"type": "Social",
"format": "Visual",
"immersion": "picture"
},
I am getting a Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object into type "MyProject.SessionModel" because the type requires a JSON array to deserialize correctly. To fix this error either change the JSON to a JSON array or change the deserialized type so that it is a normal .NET type 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. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'firstSession', line 2, position 17.
How can I convert the json string to a json array? Or make one of the other modifications the debugger suggests?
you need to create a wrapper class (json2csharp.com will help you do this)
public class Root {
public List<SessionModel> firstSession { get; set; }
}
then
var data = JsonConvert.DeserializeObject<Root>(json);
data.firstSession will be a List<SessionModel>
Create a new Class and have firstSession as List of SessionModel.
public class Sessions
{
public List<SessionModel> firstSession { get; set; }
}
Remove IEnumerable from the SessionModel
public class SessionModel
{
public int block { get; set; }
public string name { get; set; }
public string title { get; set; }
}
Change thedeserialization part as follows
var data = JsonConvert.DeserializeObject(line);
foreach (SessionModel scenario in data.firstSession)
{
//Here you can get each sessionModel object
Console.WriteLine(scenario.answer);
}

How to insertmany() JSON Array in mongodb using C#

anyone know how to insert this json array into mongodb using insertmany() and C# ??
i cant find any good source for this problem
MongoCollectionBase.InsertMany expects an IEnumerable<TDocument>.
So you need to deserialize your data json element to TDocument[], (Datum) and then pass that array to InsertMany.
Based on the below json, which is different from your screenshot
{
"data": [
{
"pulsa_code": "alfamart100",
"pulsa_op": "Alfamart Voucher",
"pulsa_nominal": "Voucher Alfamart Rp 100.000",
"pulsa_price": 100000,
"pulsa_type": "voucher",
"masaaktif": "0",
"status": "active"
}
]
}
This should work
//...
public class Datum
{
public string pulsa_code { get; set; }
public string pulsa_op { get; set; }
public string pulsa_nominal { get; set; }
public double pulsa_price { get; set; }
public string pulsa_type { get; set; }
public string masaaktif { get; set; }
public string status { get; set; }
public double harga { get; set; }
}
public class PriceListPrepaidModel
{
public List<Datum> data { get; set; }
}
public class PriceList : BaseDatabase
{
//NOTE: The strongly typed IMongoCollection<T> must be the same type as the entities passed to InsertMany
private IMongoCollection<Datum> _pricelistCollection;
//private IMongoCollection<PriceListPrepaidModel> _pricelistCollection;
public PriceList(IServiceProvider serviceProvider)
{
_pricelistCollection = DB.GetCollection<PriceListPrepaidModel>("price_prepaid");
}
public ResponseModel<string> PriceListPrepaidTest(PriceListPrepaidRequest request)
{
var entityResult = new ResponseModel<string>();
try
{
Console.WriteLine(response.Content);
//Desirialize to your model class, not JObject
var model = JsonConvert.DeserializeObject<PriceListPrepaidModel>(message.AsString);
foreach (var item in model.data)
{
item.pulsa_price = (int)item.pulsa_price + 200;
}
//Insert the array of `Datum`
_pricelistCollection.InsertMany(model.data);
entityResult.Value = JsonConvert.SerializeObject(model.data);
entityResult.Status = true;
}
catch (Exception ex)
{
entityResult.Messages.Add(new ResponseMessageModel()
{
Type = ResponseMessageModel.MessageType.ERROR,
Title = "Error",
Message = ex.Message
});
}
return entityResult;
}
}

Why is deserialized object fields are coming as null when data exists?

I have a json object that I need to deserialize, I'm using Json.NET to make these operations.
when it's a simple object, its quite easy to do it, but I cant figure out how to deserialize this string
json
{
"aspsp-list":
[
{
"id":"424250495054504C",
"bic":"BBPIPTPL",
"bank-code":"0010",
"aspsp-cde":"BBPI",
"name":"BANCO BPI, SA",
"logoLocation":"../img/corporate/theBank.jpg",
"api-list":[{
"consents":["BBPI/v1/consents"],
"payments":["BBPI/v1/payments"],
"accounts":["BBPI/v1/accounts"],
"funds-confirmations":["BBPI/v1/funds-confirmations"]
}]
},
{
"id":"544F54415054504C",
"bic":"TOTAPTPL",
"bank-code":"0018",
"aspsp-cde":"BST",
"name":"BANCO SANTANDER TOTTA, SA",
"logoLocation":"../img/openBank.svc",
"api-list":[{
"consents":["BBPI/v1/consents"],
"payments":["BBPI/v1/payments"],
"accounts":["BBPI/v1/accounts"],
"funds-confirmations":["BST/v1/funds-confirmations"]
}]
}
]
}
Now the code I have so far:
internal class AspspListResponseResource
{
// Report with the list of supported ASPSPs. Each ASPSP will include the list of available API endpoints and the logo.
[JsonProperty(PropertyName = "aspsp-list")]
public AspspList[] AspspList { get; set; }
public AspspListResponseResource() { /* Empty constructor to create the object */ }
public AspspListResponseResource(string jsonString)
{
//var alrr = JsonConvert.DeserializeObject<AspspListResponseResource>(jsonString);
JObject jObject = JObject.Parse(jsonString);
JToken jUser = jObject["aspsp-list"];
// The root object here is coming with certain fields as null, such as 'aspsp-cde', 'bank-code' and 'api-list'
AspspListResponseResource root = JsonConvert.DeserializeObject<AspspListResponseResource>(jsonString);
}
}
internal class Aspsp
{
// ASPSP Id
[JsonProperty(PropertyName = "id")]
public string Id { get; set; } = "";
// Bank Identifier Code
[JsonProperty(PropertyName = "bic")]
public string Bic { get; set; } = "";
// IBAN Bank Identifier
[JsonProperty(PropertyName = "bank-code")]
public string BankCode { get; set; } = "";
// ASPSP Code to use in the endpoint
[JsonProperty(PropertyName = "aspsp-cde")]
public string AspspCde { get; set; } = "";
// Institution name
[JsonProperty(PropertyName = "name")]
public string Name { get; set; } = "";
// Bank logo location
[JsonProperty(PropertyName = "logoLocation")]
public string LogoLocation { get; set; } = "";
// Bank Supported API List
[JsonProperty(PropertyName = "api-list")]
public ApiLink[] ApiList { get; set; }
}
internal class ApiLink
{
// Consents Link List
[JsonProperty(PropertyName = "consents")]
public string[] Consents { get; set; } = { "" };
// Payments Link List
[JsonProperty(PropertyName = "payments")]
public string[] Payments { get; set; } = { "" };
// Accounts Link List
[JsonProperty(PropertyName = "accounts")]
public string[] Accounts { get; set; } = { "" };
// Balances Link List
[JsonProperty(PropertyName = "balances")]
public string[] Balances { get; set; } = { "" };
// Transaction Link List
[JsonProperty(PropertyName = "transaction")]
public string[] Transaction { get; set; } = { "" };
// Funds-Confirmations Link List
[JsonProperty(PropertyName = "funds-confirmations")]
public string[] FundsConfirmations { get; set; } = { "" };
}
Sum of the values of the deserialized object are null, even though the jsonString definitelly has data.
How should I proceed here?
The way your json is structured:
{
"aspsp-list":
[
{
"id":"123123123",
"bic":"BBPIPTPL",
"bank-code":"0010",
"aspsp-cde":"BBPI",
"name":"BANCO BPI, SA",
"logoLocation":"../img/corporate/theBank.jpg",
"api-list":[{
"consents":"",
"payments":"",
"accounts":"",
"funds-confirmations":""
}]
},
{
"id":"1434231231",
"bic":"TOTAPTPL",
"bank-code":"0018",
"aspsp-cde":"BST",
"name":"BANCO SANTANDER TOTTA, SA",
"logoLocation":"../img/openBank.svc",
"api-list":[{
"consents":"",
"payments":"",
"accounts":"",
"funds-confirmations":""
}]
}
]
}
This is telling us that you have an object, with an array of objects called Aspsp-list.
If this is what you intended great.
We need to create an object similar to this
public class RootJsonObject {
public IEnumerable<Aspsp> Aspsp-list {get; set;}
}
To deserialize to this simply:
JsonConvert.Deserialize<RootJsonObject>(/*your json string*/ value);
If you wanted to only work with the array, you would need to deserialize purely to an IEnumerable/Array But you would also need to change your json to just be an array, not an object wrapping an array.
I managed to make it work now, my problem wasn't exactly that I couldn't deserialize because of data types or structure (at least not completely, comment that said that the structure was wrong was partly right).
So, this is how I solved the problem:
-> Created an empty costructor on the AspspListResponseResource class, so that the method JsonConvert.DeserializeObject<T>(jsonString) could create an instance of the object, I thought of this since the only constructor took a string, and so there was no other contructor for JsonConvert to use.
-> Put the field names of with help of [JsonProperty(PropertyName = "")], but this still gave me the deserialized object as null, or with some null fields.
-> commented the fields Transaction and FundsConfirmations of the ApiLink class, these fields were in the documentation of the Web API so I put them in, but looking at the json string I recieve, it look like they aren't being used, so I just commented them
and after these changes the code now works flawlessly:
The code:
internal class AspspListResponseResource
{
// Report with the list of supported ASPSPs. Each ASPSP will include the list of available API endpoints and the logo.
[JsonProperty(PropertyName = "aspsp-list")]
public Aspsp[] AspspList { get; set; }
public AspspListResponseResource() { /* Empty constructor to create the object */ }
public AspspListResponseResource(string jsonString)
{
AspspListResponseResource root = JsonConvert.DeserializeObject<AspspListResponseResource>(jsonString);
this.AspspList = root.AspspList;
}
}
internal class Aspsp
{
// ASPSP Id
[JsonProperty(PropertyName = "id")]
public string Id { get; set; } = "";
// Bank Identifier Code
[JsonProperty(PropertyName = "bic")]
public string Bic { get; set; } = "";
// IBAN Bank Identifier
[JsonProperty(PropertyName = "bank-code")]
public string BankCode { get; set; } = "";
// ASPSP Code to use in the endpoint
[JsonProperty(PropertyName = "aspsp-cde")]
public string AspspCde { get; set; } = "";
// Institution name
[JsonProperty(PropertyName = "name")]
public string Name { get; set; } = "";
// Bank logo location
[JsonProperty(PropertyName = "logoLocation")]
public string LogoLocation { get; set; } = "";
// Bank Supported API List
[JsonProperty(PropertyName = "api-list")]
public ApiLink[] ApiList { get; set; }
}
internal class ApiLink
{
// Consents Link List
[JsonProperty(PropertyName = "consents")]
public string[] Consents { get; set; } = { "" };
// Payments Link List
[JsonProperty(PropertyName = "payments")]
public string[] Payments { get; set; } = { "" };
// Accounts Link List
[JsonProperty(PropertyName = "accounts")]
public string[] Accounts { get; set; } = { "" };
// Balances Link List
[JsonProperty(PropertyName = "balances")]
public string[] Balances { get; set; } = { "" };
//// Transaction Link List
//[JsonProperty(PropertyName = "transaction")]
//public string[] Transaction { get; set; } = { "" };
//
//// Funds-Confirmations Link List
//[JsonProperty(PropertyName = "funds-confirmations")]
//public string[] FundsConfirmations { get; set; } = { "" };
}
You need to create a contructor for the ApiLink class so you can do the following:
var apiListRaw = new ApiLink(value["api-list"][0] as JObject);
The constructor would look something like the following:
public ApiLink(JObject json)
{
Consensts = (string[])json["consents"];
...
}

How do I create a Dictionary<string,string> for nested object

I am retrieving the following JSON via a POST to an API
{
"State":"Andhra_Pradesh",
"District":"Guntur",
"Fact":"SELECT",
"Description":"",
"FactDate":"",
"FactNumber":"",
"FactType":"SELECT",
"Fact":{"Id":"1"}
}
I am able to execute the Ajax request via javascript, but I also want to consume the API through C# code.
I am using the below code, but I'm not quite sure on how to add the Fact object?
var values = new Dictionary<string, string>
{
{ "State", selectedState },
{ "District", selectedDistrict },
{ "Fact", ""},
{ "FactType", ""},
{ "FactNumber", ""},
{ "Description", ""},
{"Fact", "{Id,1}" },
{"FactDate", factDate.Date.ToString() }
};
using (var httpClient = new HttpClient())
{
var content = new FormUrlEncodedContent(values);
var response = await httpClient.PostAsync("http://api.in/" + "test", content);
}
How do I add the Fact object to Dictionary?
You'll probably need to define the data you are sending as actual class before using httpclient.
If you had only name value pairs then you could have used the NameValueCollection and sent as a formurlencoded but since you have a complex type, you might consider this below.
See below.
public class Rootobject
{
public string State { get; set; }
public string District { get; set; }
public Fact Fact { get; set; }
public string Description { get; set; }
public string CaseDate { get; set; }
public string FactNumber { get; set; }
public string FactType { get; set; }
}
public class Fact
{
public string Id { get; set; }
}
Usage is as below. be sure to include a reference to System.Net.Http.Formatting.dll
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var model = new Rootobject { State = "Andhra_Pradesh", District = "Guntur", FactType = "SELECT", Description = "", CaseDate = "", FactNumber = "", Fact = new Fact { Id = "1"} };
var data = await client.PostAsJsonAsync("http://api.in/" + "test", model);
I think this is just a json object, you can either create a class which have the same properties of (state, district etc ..) and use json serializer
or you can create JObject using Json.Net
You can use Newtonsonft.Json to to the serializaton/deserialization job and the code will be like that.
public class Rootobject
{
[JsonProperty("State")]
public string State { get; set; }
[JsonProperty("District")]
public string District { get; set; }
[JsonProperty("Fact")]
public Fact Fact { get; set; }
[JsonProperty("Description")]
public string Description { get; set; }
[JsonProperty("CaseDate")]
public string CaseDate { get; set; }
[JsonProperty("FactNumber")]
public string FactNumber { get; set; }
[JsonProperty("FactType")]
public string FactType { get; set; }
}
public class Fact
{
[JsonProperty("Id")]
public string Id { get; set; }
}
And then, after instatiating your object, just serialize it.
Rootobject example = new Rootobject();
//Add values to the variable example.
var objectSerialized = JsonConvert.SerializeObject(example);
After that, you will have a json ready to be send wherever you want.
Just change {"Fact", "{Id,1}" } to {"Fact.Id", "1" },

How to design class for abstract json document?

Suppose we have class Request which we want to serialize to json and deserialize from json.
class Request {
public string SessionId { get; set; }
...
public string InnerJson { get; set; }
}
As json it should looks like
{
"SessionId": 1,
...
"InnerJson": {
"some": "json object",
"whatever": 666
}
}
InnerJson is some json document (arbitrary type).
Is it good to use string for InnerJson in Request?
Is there any good way to design Request class?
If you are going for a strongly typed model I'd suggest a factory. For demonstration sake:
public abstract class AbstractOptions { }
public class Options1 : AbstractOptions { public int Whatever { get; set; } }
public class Options2 : AbstractOptions { public string Some { get; set; } }
public class Options3 : AbstractOptions {
[JsonProperty("when")] public DateTime When { get; set; }
[JsonProperty("inner")] public InnerComplexObject Inner { get; set; }
}
public class Request {
[JsonProperty("session-id")] public string SessionId { get; set; }
[JsonProperty("options")] public AbstractOptions Options { get; set; }
}
public class InnerComplexObject { }
then use it like:
var req1 = new Request() { SessionId = "s1", Options = new Options1 { Whatever = 123 } };
var req2 = new Request() { SessionId = "s2", Options = new Options2 { Some = "some" } };
var req3 = new JToken.Request() { SessionId = "s3", Options = new Options3 { When = DateTime.UtcNow, Inner = new InnerComplexObject() } };
Otherwise, for flexibility, keep InnerJson a string and use dynamic queries.

Categories