Ignore custom children with Json .Net - c#

i have a json response like this:
{"response_values":[110,{"id":14753,"name":"piter"},{"id":14753,"name":"rabbit"}]}
and i have a simple class
public class Class1
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
and when i trying to convert json to list of the objects with this method:
public T Cast<T>(string json)
{
var result = default(T);
var jsonObject = JObject.Parse(json);
if (jsonObject != null)
{
var responseToken = jsonObject["response"];
result = responseToken.ToObject<T>();
}
return result;
}
like this
...
var jsonString = GetJson();
var items = Cast<List<Class1>>();
...
i have an exceiption, because value "110" is integer. How can i skip this value?

You always have this option if you expect the values to ignore to always be at the beginning:
if (jsonObject != null)
{
var responseToken = parsed["response_values"].SkipWhile(j => j.Type != JTokenType.Object);
if (responseToken.Count() > 0) result = responseToken.ToObject<T>();
}
You may prefer to use Skip(1) instead of SkipWhile if it's always the first value. Alternatively, you can use Where to ignore or select tokens anywhere in the message.
Of course, you can play around with this approach (changing things) depending on exactly what you expect to be returned in success scenarios.

Related

Get field from a sub object in MongoDB

I have the following document in MongoDB and I want to check if the field FileName has a specific value.
Following are my classes:
public class Invoice
{
private InvoiceMetaData _metadata = null;
private List<InvoiceColumns> _invoiceFields = null;
public InvoiceMetaData Metadata
{
get
{
if (_metadata == null) _metadata = new InvoiceMetaData();
return _metadata;
}
set { _metadata = value; }
}
public List<InvoiceColumns> InvoiceFields
{
get
{
if (_invoiceFields == null)
_invoiceFields = new List<InvoiceColumns>();
return _invoiceFields;
}
set { _invoiceFields = value; }
}
}
public class InvoiceMetaData
{
public string FileName { get; set; }
public string FileProcessedOn { get; set; }
public string DirectoryPath { get; set; }
}
I've tried using the following but it's returning false even though documents with this filename exist.
string filename = "01.png";
var collection = myDB.GetCollection<Invoice>(collection_name);
var exists = collection.AsQueryable().Any(avm => avm.Metadata.FileName == filename);
I've also tried this but it's returning nothing i.e. List count is 0.
var query = Query<Invoice>.EQ(u => u.Metadata.FileName, filename).ToBsonDocument();
var exist = collection.Find(query).ToList();
Also tried this and list Count is 0,
var filter1 = Builders<Invoice>.Filter.Eq(u => u.Metadata.FileName, filename, filename);
var result = collection.Find(filter1).ToList();
Can anyone please tell me what am I doing wrong?
Any help will be much appreciated.
I haven`t worked with this for a while. But this can be helpful for you:
how to check if a field exists in a specific document Mongodb using C#?
As i remeber, you can do something like that:
var collection = myDB.GetCollection<BsonDocument>(collection_name); // you use Invoice, try BsonDocument
var documents = collection.Find(new BsonDocument()).ToList(); // this one should get you all documents
var fieldName = "Metadata" // name of field you need data from
foreach (var document in documents)
{
// this one should contain your metadata object from document, note it is BsonDocument
var metaDataObject= document.Contains(fieldName) ? document[fieldName].ToBsonDocument() : null;
var fileName= metaDataObject!= null ? metaDataObject["FileName"] : "No file name."; // should be your file name
// you also should be able to convert to dictionary, under this namespace MongoDB.Bson.BsonDocument
// var metadataDic= metaDataObject.ToDictionary();
// var fileName= metadataDic["FileName"]; // should be your file name
}
Filter examples:
var builder = Builders<BsonDocument>.Filter; // in your example invoice, try BsonDocument
var filter = builder.Eq("FileName", fileName);
var count = collection.Count(filter);

Deserialize JSON to list with unknown object name in C#

I want to deserialize following JSON.
The problem is that the objects "ANDE" & "DAR" can change.
Means the objects are unknown and change depending on the JSON i wanna deserialize.
About 8000 different objects (ANDE, DAR, ...) need to be deserialized.
{"ANDE":
{"chart":[
{"date":"20180914","minute":"09:30"},{"date":"20180914","minute":"13:30"}]},
"DAR":
{"chart":[
{"date":"20180914","minute":"09:30"},{"date":"20180914","minute":"13:30"}]}}
I get the data by HTTP response and want to put into a List:
HttpResponseMessage response = client.GetAsync(API_PATH).GetAwaiter().GetResult();
List historicalDataList = response.Content.ReadAsAsync<List<HistoricalDataResponse>>().GetAwaiter().GetResult();
The HistoricalDataResponse class looks like:
public class HistoricalDataResponse
{
public string date { get; set; }
public string minute { get; set; }
}
How can i deserialize this kind of JSON with unknown objects in C#?
Any help is highly appreciated.
Then you should use a dynamic variable:
dynamic ReturnValue = JsonConvert.DeserializeObject(jsonstring);
note that as in dynamic objects, properties are determined after being assigned in runtime, so you will not get a drop down menu in design time, and also as its properties are unknown in design time, and property you test in design time even if its not correct, you wont get an error, and you will get the error in runtime when it is assigned.
dynamic ReturnValue = JsonConvert.DeserializeObject(jsonstring);
try
{
var a = ReturnValue.ANDE; // will work if it has ANDE property.
// do what you would do with ANDE
}
catch{}
try
{
var a = ReturnValue.DAR; // will work if it has DAR property.
// do what you would do with DAR
}
catch{}
Use a dictionary with string as key type :
void Main()
{
var client = new HttpClient();
HttpResponseMessage response = client.GetAsync("url").GetAwaiter().GetResult();
var json = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
var result = JsonConvert.DeserializeObject<Dictionary<string, DateResponse>>(json);
foreach (var element in result)
{
var key = element.Key; // ANDE
foreach (var item in element.Value.Chart)
{
var date = item.date;
var minute = item.minute;
}
}
}
public class DateResponse{
public List<HistoricalDataResponse> Chart { get; set; }
}
public class HistoricalDataResponse
{
public string date { get; set; }
public string minute { get; set; }
}

How can i see if my JSON contains a certain value and then compare it?

var Name = "Resources.myjson.json";
var NameJSON = new System.IO.StreamReader(typeof(Strings).GetTypeInfo().Assembly.GetManifestResourceStream(Name)).ReadToEnd();
var ParsedBrandJSON = Newtonsoft.Json.JsonConvert.DeserializeObject<TheInfo>(NameJSON);
await JsonCS.LoadJson(ParsedBrandJSON);
And on the page:
static public class TheInfoJSON
{
static public TheInfo Data { get; set; }
static public async Task LoadJson(Data JSON)
{
Data = JSON;
}
}
and
public class TheInfo
{
public List<TheName> TheName { get; set; } = new List<TheName>();
}
My json:
{
"TheInfo":[
{
"TheName": ["Martin", "Jonas", "Alex", "Oscar"]
}
]
}
When i now try to compare how can i see if my JSON contains a certain object and then store that as a single TheName? Is it possible to do it in the same cast?
var TheNameDataFromOtherPage = OtherPage.TheName; //Here i gather the name from another page that i will compare with the JSON
//Wrong syntax
bool DoTheyMatch = TheNameDataFromOtherPage == TheInfoJSON.Data.TheName.Contains("Alex");
This is now wrong syntax because i cant compare the value to a bool. How can i get out the data i find and then instead of having TheInfoJSON.Data.TheName.Contains("Alex"); as a bool, back to a single value of TheName containing "Alex" so I can create a bool out of the two values to see if the JSON has it or not.
I tried to add something along the lines like this after the contains(): as TheInfo.TheName but that isnt the correct syntax either.
bool DoTheyMatch = TheInfoJSON.Data.TheName.Contains(TheNameDataFromOtherPage);

How can I convert data held as 01010 bits into fields in a class object?

I have two variables that contain true/false data. THe first variable can be null but the second variable is always non null. Both variables will always be the same length.
var AnswerGridCorrect = "000111"; // or null
var AnswerGridResponses = "000011";
How could I change this data into an object oriented form. I already created classes and these are below. Here's is what I need the output to look like when converted to JSON:
"answers":[ // Json conversion made Answers into answers
{"correct":null,"response":true},
{"correct":null,"response":true},
{"correct":null,"response":true},
{"correct":null,"response":false}
}
Note that I am using LINQ to output the data so I think what I need is a function with parameters something like this:
.Select((t, index) => new {
Answer = t.Answer,
Answers = makeAnswer(t.AnswerGridCorrect,
t.AnswerGridResponses)
});
I am not sure if this helps but here were the classes I was using when I did this from JSON:
public class AnswerRow
{
public bool? Correct { get; set; }
public bool Response { get; set; }
}
public class AnswerRowList
{
public IList<AnswerRow> AnswerRows { get; set; }
}
Here is an implementation for your makeAnswers method:
public List<AnswerRow> makeAnswers(string c, string r)
{
var result = new List<AnswerRow>();
for(var i=0; i<r.Length; i++)
{
result.Add(
new AnswerRow {
Correct = c!=null?new Nullable<bool>(c[i]=='1'):null,
Response = r[i]=='1'
});
}
return result;
}
Rene's answer is probably correct, but here's the (unnecessarily complex) Linq way:
AnswerRowList MakeAnswer(string answerGridCorrect, string answerGridResponses)
{
return new AnswerRowList()
{
AnswerRows = answerGridResponses.Zip(
answerGridCorrect == null ?
Enumerable.Repeat<bool?>(null, answerGridResponses.Length) :
answerGridCorrect.Select(x => new Nullable<bool>(x == '1')),
(r, c) => new AnswerRow()
{
Correct = c,
Response = r == '1'
}).ToList()
};
}

Linq object properties disappear after serialization

I'm trying to understand the included code snippets behavior, it doesn't work as I'd expect. Here is what I'm doing:
Serialize a LINQ object to JSON
Deserialize the JSON at (1) back in its initial type
Validate that each property are still in the Object
I serialize the object from (2) back to JSON
Print the json from (4) and visually inspect it
My issue is that at (5), any LINQ entity that is a property of the main LINQ object is gone, even tho it was still there when on validation at (3). All my LINQ classes are LINQ to SQL. I am using Newtons JSON.Net library. I tried the same type of logic with non-linq object and the defect seen at (5) doesn't occur.
var infoId = Guid.NewGuid();
var alertId = Guid.NewGuid();
var info = new Info();
info.InfoId = infoId;
var alert = new Alert();
alert.AlertId = alertId;
alert.Infos.Add(info);
var json = JsonConvert.SerializeObject(alert);
Debug.WriteLine(json); //All looking good, nothing missing
var deserializedObject = JsonConvert.DeserializeObject<Alert>(json);
Assert.AreEqual(alertId, deserializedObject.AlertId); //Assert is valid
Assert.AreEqual(infoId, deserializedObject.Infos[0].InfoId); //Assert is valid
var json2 = JsonConvert.SerializeObject(deserializedObject);
Debug.WriteLine(json2); //Infos is gone
Update:
I have done some debbugging, and in the Serialization of deserializedObject
var json2 = JsonConvert.SerializeObject(deserializedObject);
I see the following when reaching the Info Serialization step (next code snipped):
this.serializing is true
this._Infos.HasLoadedOrAssignedValues is false
The get return null is called. (get returns the null value)
If I put a breakpoint, and put my cursor on the return this._Infos I actually see the object that It should return ...
[global::System.Data.Linq.Mapping.AssociationAttribute(Name="Alert_Info", Storage="_Infos", ThisKey="AlertId", OtherKey="AlertId")]
[global::System.Runtime.Serialization.DataMemberAttribute(Order=15, EmitDefaultValue=false)]
public EntitySet<Info> Infos
{
get
{
if ((this.serializing && (this._Infos.HasLoadedOrAssignedValues == false)))
{
return null;
}
return this._Infos;
}
set
{
this._Infos.Assign(value);
}
}
Update:
This leads me to believe that I might need to find a way to modify the default value of HasLoadedOrAssignedValues when it is being deserialized from Newtons Json.Net.
I also found a dirty fix, which I don't really like that seems to be working:
var deserializedObject = JsonConvert.DeserializeObject<EasAlert>(json);
var list = new List<EasInfo>();
deserializedObject.EasInfos.SetSource(list); //<--- Fix, the Info will show up in json2
Assert.AreEqual(alertId, deserializedObject.AlertId);
Assert.AreEqual(infoId, deserializedObject.EasInfos[0].InfoId);
I was trying Microsoft's JavaScriptSerializer, and it worked fine. Code and output can be found below.
Could it be a bug in Newton's?
void Main()
{
var infoId = Guid.NewGuid();
var alertId = Guid.NewGuid();
var info = new Info();
info.InfoId = infoId;
var alert = new Alert();
alert.AlertId = alertId;
alert.Infos.Add(info);
var jss = new JavaScriptSerializer();
var json = jss.Serialize(alert); //JsonConvert.SerializeObject(alert);
Debug.WriteLine(json); //All looking good, nothing missing
var deserializedObject = jss.Deserialize<Alert>(json); //JsonConvert.DeserializeObject<Alert>(json);
(alertId == deserializedObject.AlertId).Dump(); //Assert is valid
(infoId == deserializedObject.Infos[0].InfoId).Dump(); //Assert is valid
var json2 = jss.Serialize(deserializedObject); //JsonConvert.SerializeObject(deserializedObject);
Debug.WriteLine(json2); //Infos is gone - NOT GONE!
}
public class Alert
{
public Guid AlertId { get; set; }
public List<Info> Infos { get; set; }
public Alert()
{
Infos = new List<Info>();
}
}
public class Info
{
public Guid InfoId { get; set; }
}
Output:
{"AlertId":"0340e855-065c-4ac7-868e-5999fa4b7862","Infos":[{"InfoId":"31e269a1-4354-423d-84bc-62f6dc06b10f"}]}
True
True
{"AlertId":"0340e855-065c-4ac7-868e-5999fa4b7862","Infos":[{"InfoId":"31e269a1-4354-423d-84bc-62f6dc06b10f"}]}
check Alert class (constructor)
public class Alert{
public Guid AlertId{get;set;}
public List<Info> Infos {get;set;}
public Alert() {
Infos = new List<Info>();
}
}
looks like you are missing List init
even with EntitySet

Categories