I am trying to deserialize JSON. My root object has a single property "en.pickthall". I am using dynamic type for reading my JSON. I thought I could just do away with "." in the property since its a local JSON file but then there must be some way to access such a property
var result = App_Code.FileIOHelper.ReadFromDefaultFile("ms-appx:///Assets/en.pickthall.json");
dynamic stuff = JsonConvert.DeserializeObject(result);
foreach(var x in stuff.(en.pickthall)) //Tried this intellisense didn't like it
{
}
You could create a root class to deserialize into and use JsonProperty
public class Root
{
// Use the proper type instead of object
[JsonProperty(PropertyName = "en.pickthall")]
public IEnumerable<object> EnPickthall { get; set; }
public Root() { }
}
Used as follows
Root stuff = JsonConvert.DeserializeObject<Root>(result);
foreach(var x in stuff.EnPickthall)
{
}
You could serialize not to dynamic but to JObject and then access your property via
JObject stuff = JsonConvert.DeserializeObject<JObject>(Jsonstring);
var x = stuff.Value<String>("my.property")
C# doesn't have any way of quoting identifiers. If it's not a valid identifier, your only option is reflection.
However, it's possible the object returned by your JSON deserializer changed the identifiers to make them useable in C# - you might want to enumerate all the properties to check if that is the case. A dynamic object with indexers might also be a solution (allowing e.g. stuff["en.pickthall"]).
Another alternative is to change the way the serializer maps properties. For example, Newtonsoft.Jsoft allows you to customize this using a IContractResolver. It's quite easy to replace the . for something more C#-sane in this way.
I know you said you were using a dynamic type for your JSON deserialization, but I just wanted to point out that there is a .NET RESTful client out there that supports this with static model definitions too. For you or for anyone else who happens upon this response when searching for an answer to their problems with dots in property names in C# REST calls.
As of the newly released RestSharp 106.1.0 (and I do mean this version because this support was just added), it can handle renaming properties with a dot in their name via the DeserializeAs attribute. An example being when I call the ElasticSearch API for a _cat call with the following model:
public class CatResponse
{
public string index { get; set; }
...
[DeserializeAs(Name = "docs.count")]
public string docscount { get; set; }
}
And actually get back the docs.count property deserialized into docscount now:
var resource = $"_cat/indices/{indexPattern}?format=json&pretty=true";
var request = new RestRequest(resource, Method.GET);
var response = client.Execute<List<CatResponse>>(request);
This support is out of the box and doesn't need to use the Newtonsoft.Json.JsonSerializer which I have also heard is a possible solution to this problem but which I couldn't get to work.
With a dynamic object and NewtonSoft.Json:
dynamic json = JValue.Parse(result);
int Opens = Convert.ToInt32(json.opens);
int Clicks = Convert.ToInt32(json.clicks);
string State = json.state;
Related
I try to use Json.NET for consuming an OData (like) service. My data structures have collection properties.
However all those properties are wrapped in a property called 'results' by my service. Even the main query which returns with a collection of the entities are wrapped into a root property called results.
Although I am not an OData expert I think this is pretty much a standard because if I try to send an object graph for update, and omit this 'results' wrapper around say a int collection type property then I got an error message from the server "A collection was found without the 'results' property. In OData, each collection must be represented as a JSON object with a property 'results'"
So I understand the server error message, and I also know how to workaround this. Of course I can mimic this object graph in my C# object model, but after writing the 101st wrapper in my object model it tends to be boring, and I do not want to reinvent the wheel.
My question is there an out of the box solution how to deal with this result property, and make it transparent? If this is a 'standard' I suppose not I am the first who are facing this task.
Thanks in advance
you can just write one and use it everywhere
public class OData<T> where T : IEnumerable
{
public T results { get; set; }
}
public class X
{
public string Prop { get; set; }
public OData<List<int>> List { get; set; }
}
class Program
{
static void Main(string[] args)
{
var x = new X()
{
Prop = "test",
List = new OData<List<int>> {results = new List<int>() {1, 2, 3}}
};
Console.WriteLine(JsonConvert.SerializeObject(x));
}
}
I am retrieving JSON from an API. I am using newtonsoft (this is json.net right?) to deserialize this into a list of objects. It works.
Unfortunately I also need to pass this along to someone else as JSON (they can't call the API directly only I have access to it). I say unfortunately because I need to OUTPUT my JSON that is different from what is being received (the property names need to be different).
For example, I have a class called Person, with a property called Name. I want to get "People", so I make my request to that API to get JSON as above, and get back a list of Person. Unfortunately the API doesn't return me people with Name properties, it returns me pname. So to map this, I just do:
[JsonProperty("pname")]
This is all well and good - it converts pname to name and my class now has the value! I have a list of people with names.
Now I need to give this list of objects BACK to someone else as "Name", However when I serialize my people class back to JSON, it writes out the JSON as "pname" when I really want to write it out as "Name". I suspect it's picking up the "JsonProperty".
Is there a way to just have it use pname for deserialization, but use the original property value for serialization?
Thanks!
You can create a custom contract resolver that sets the property names back to the ones you've defined in the C# class before serilization. Below is some example code;
class OriginalNameContractResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
// Let the base class create all the JsonProperties
IList<JsonProperty> list = base.CreateProperties(type, memberSerialization);
// assign the C# property name
foreach (JsonProperty prop in list)
{
prop.PropertyName = prop.UnderlyingName;
}
return list;
}
}
Use it like this;
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Formatting = Formatting.Indented;
if (useLongNames)
{
settings.ContractResolver = new OriginalNameContractResolver();
}
string response = JsonConvert.SerializeObject(obj, settings);
Maybe I'm late to the party, but this also works:
[JsonPropertyName("pname")]
public string? PName { private get; set; }
public string? Name => PName;
You might be able to write a custom JsonConverter to do it with just one Person class, but I'd recommend having separate classes, since the data is modeled differently in the two places. Even if you don't plan to right now, you might find yourself needing to deserialize from Name or serialize to pname at some point. This also allows your classes to differ more substantially. You could use AutoMapper (or similar) to easily convert between the two. E.g.
public class PersonFromThatApi
{
[JsonProperty("pname")]
public string Name { get; set; }
}
public class Person
{
public string Name { get; set; }
}
Mapper.CreateMap<PersonFromThatApi, Person>();
Mapper.CreateMap<Person, PersonFromThatApi>();
var person1 = JsonConvert.DeserializeObject<PersonFromThatApi>(
#"{""pname"":""George""}");
Person person2 = Mapper.Map<Person>(person1);
string s = JsonConvert.SerializeObject(person2); // {"Name":"George"}
And yes, Newtonsoft.Json is the namespace of Json.NET. Don't ask me why they chose totally different names for those two things.
The simple solution is to create two properties.
I'm sure this question has been asked over and over again, but for some reason, I still can't manage to get this to work.
I want to deserialize a JSON object that contains a single member; a string array:
[{"idTercero":"cod_Tercero"}]
This is the class that I'm trying to deserialize into:
[DataContract]
public class rptaOk
{
[DataMember]
public string idTercero { get; set; }
public rptaOk() { }
public rptaOk(string idTercero)
{
this.idTercero = idTercero;
}
}
This is the method that I try to deserialize:
public T Deserialise<T>(string json)
{
DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(T));
using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
T result = (T)deserializer.ReadObject(stream);
return result;
}
}
And so I try to fill the object:
rptaOk deserializedRpta = deserializarOk(rpta);
But for some reason, this returns ""
MessageBox.Show(deserializedRpta.idTercero);
Without any dependencies outside of the .net framework, you could do it this way
[DataContract(Name="rptaOk")]
public class RptaOk
{
[DataMember(Name="idTercero")]
public string IdTercero { get; set; }
}
[CollectionDataContract(Name="rptaOkList")]
public class RptaOkList : List<RptaOk>{}
var stream = new StreamReader(yourJsonObjectInStreamFormat);
var serializer = new DataContractSerializer(typeof(RptaOkList));
var result = (RptOkList) serializer.ReadObject(stream);
I don't know if your're wiling to change the library that you're using, but I use library "Newtonsoft.Json" to desserialize JSON objects, it's pretty easy to use
[HttpPost]
public void AddSell(string sellList)
{
var sellList = JsonConvert.DeserializeObject<List<Sell>>(sellListJson);
BD.SaveSellList(sellList);
}
As you can see you can deserialize a whole json object list to a List<> fo the type "Sell", an object that i've created... And, of course, you can do that to an array too. I don't know the correct syntax for this, but you can convert this list to an array afterwards
Hope this helps
I think you're making this a lot more difficult than it needs to be. Firstly, your sample json and the class you're trying to deserialize into do not have an array of strings. They have a single property of type string. Secondly, why are you using this class DataContractJsonSerializer? You're not doing anything with it that you can't get from a simple call to json.NET's generic deserialization method. I would remove all of your code except the class definition and replace it with this simple one liner;
rptaOk[] myInstances = JsonConvert.DeserializeObject<rptaOk>(jsonString);
Also, no matter what the structure of your json is, if you have a class to correctly model it that method will correctly deserialize it. If you want to enforce some kind of contract I recommend using json schemas which json.NET also supports. If you use a schema it enforces a rigid contract, if you attempt to deserialize into an object there is something of an implicit contract. I don't know every scenario which will cause it to throw, but if your json is too far from the class definition it will. If your class has properties that don't appear in the json I believe they will just get initialized with the default values for that type.
EDIT: I just noticed your json is actually an array of objects. So you simply need to make the lhs of that assignment an array or rptaOk objects, rather than a singleton.
I have a slight situation. I'm interacting with a web service using RestSharp, where the service is requiring me to send the following as part of the request:
{
"a":"a value",
"b":"b value"
}
Which is all fine and dandy, because you could simply use a class such as this:
public class MyClass
{
public string A { get; set; }
public string B { get; set; }
}
However, I do not know know the property names at runtime. Therefore, I attempted to use an ExpandoObject, but of course, this simply serialized as a JSON array:
[
"a":"a value",
"b":"b value"
]
So, it would seem that I need to be able to serialize (and deserialize) a Dictionary (or IEnumerable<KeyValuePair<string, string>>) as a JSON object (in other words, use curly braces instead of a brackets).
Does anyone know how I might do this, preferably by using a Json.NET attribute, such that the functionality may be reused elsewhere?
how about using a JObject?
var obj = new JObject();
obj["One"] = "Value One";
obj["Two"] = "Value Two";
obj["Three"] = "Value Three";
var serialized = obj.ToString(Formatting.None);
gives you
{"One":"Value One","Two":"Value Two","Three":"Value Three"}
Use JavascripSerializer object from .net class libs. It supports reflection on the object it is serializing
see msdn docs
Is it possible to remove a property from class at runtime, like:
public Class A
{
public int num1 {get;set;}
public int num2 {get;set;}
public int num3 {get;set;}
}
Class A Obj = new A();
At run time I want to remove num2 from obj. Is it possible?
This can't be done. Once compiled, a class definition is set.
As others said already, it's not possible.
Instead you can add another property e.g.
public List<string> ignoredProperties {get; set;}
Then at runtime add num2 to that list and check it for properties you should ignore.
You have to comeup with Model/ViewModel approach. Create a ViewModel which will have limited properties for your requirement.
I agree with Nic reply: This can't be done. Once compiled, a class definition is set.
But you can create a class property dynamically what you want by reflection.
My case was much easier
I have a class which is POST
then I need to remove few properties and save this to JSON
I did go around with System.Dynamic.ExpandoObject copy the class
Object value;
System.Dynamic.ExpandoObject cloneData = JsonSerializer.Deserialize<ExpandoObject>(JsonSerializer.Serialize(data));
cloneData.Remove("IP", out value);
value = value;
cloneData.Remove("analytics", out value);
value = value;
string azurecontainer = #"data";
string azureblobJSONDataFilename = #"profile/" + _userInfoSessionB.u + #".json";
string JSONData = JsonSerializer.Serialize(cloneData);
object p = azureStorage.UploadBlob2ContainerTextAsync(JSONData, azurecontainer, azureblobJSONDataFilename, "application/json", "public, max-age=30");
I was not able to REMOVE the property, I was trying to create a dynamic JSON, with 2 different classes merged together but without some properties (not needed for that merged class), so what I did was, I added a custom attribute and added to field/properties which I didn't need, and used reflection to create a custom JSON at runtime after merging 2 classes.
I had a very exact use case. In my case, I want to ignore some properties when posting the data model to ODATA via Json. This property may not be a table field so I want to ignore while serializing this to JSON. I achieved this by below steps.
I used the DataAnnotations to decorate that attribute as [ReadOnly(true)]
I then created a custom JsonSerializer from ISerializer to ignore the ReadOnly Properties like below:
public string Serialize(object obj)
{
return JsonSerializer.Serialize(obj,
new JsonSerializerOptions
{
IgnoreReadOnlyProperties = true
});
}
This solved my problem to ignore some properties that I don't want to pass via Json/OData calls or any Api/endpoint wherever it is.
//Convert your object to JObject
var jsonDoc = JObject.FromObject(doc);
//Select the Property To Remove
var PropertyToRemove= jsonDoc.Property("PropertyToRemove");
// Remove the Property
sig.Remove();