JSON cannot get data - c#

Hi I'm trying to parse a JSON page in C#, but I can't seem to read some strings, like:
"versions": [
{
"date": 1340466559,
"dl_link": "http://dev.bukkit.org/media/files/599/534/NoSwear.jar",
"filename": "NoSwear.jar",
"game_builds": [
"CB 1.2.5-R4.0"
],
"hard_dependencies": [],
"md5": "d0ce03e817ede87a9f76f7dfa67a64cb",
"name": "NoSwear v5.1",
"soft_dependencies": [],
"status": "Semi-normal",
"type": "Release"
},
How could I read that?
This is the code I have right now and works for everything else except this:
public static void GetMoreInfo(string plugin)
{
try
{
string url = "http://bukget.org/api/plugin/";
var wc = new WebClient();
var json = wc.DownloadString(url + plugin);
var moreInfo = JsonConvert.DeserializeObject<MoreInfo>(json);
foreach (var category in moreInfo.categories)
{
Categories += category + ", ";
}
Categories = Categories.Remove(Categories.Length - 2, 2);
}
catch (Exception)
{
}
finally
{
if (string.IsNullOrEmpty(Categories))
{
Categories = "No data found.";
}
}
}
public class MoreInfo
{
public string[] categories;
}

How about handling your json dynamically, instead of deserializing to a concrete class?
var wc = new WebClient();
var json = wc.DownloadString("http://bukget.org/api/plugin/test");
dynamic moreInfo = JsonConvert.DeserializeObject(json);
Console.WriteLine("{0} {1} {2}", moreInfo.name, moreInfo.desc, moreInfo.status);
string categories = String.Join(",", moreInfo.categories);
Console.WriteLine(categories);
Or would you prefer the classical approach?
var plugin = JsonConvert.DeserializeObject<Plugin>(json);
string categories = String.Join(",",plugin.categories);
public class Plugin
{
public List<string> authors;
public string bukkitdev_link;
public List<string> categories;
public string desc;
public string name;
public string plugin_name;
public string status;
public List<Version> versions;
}
public class Version
{
public string date;
public string filename;
public string name;
//.......
}

I could be wrong, but the JSON you're receiving is an array named versions but you're trying to deserialize it into a MoreInfo object that exposes an array named categories (unless it's just a typo in your example). Have you tried renaming MoreInfo.categories to MoreInfo.versions?
UPDATE
I don't think that would make a difference because the JSON converter doesn't know what to do with each object in the array. You need to provide an object to deserialize each element in the JSON array.
For example, try modifying the MoreInfo object to include matching properties to the JSON string (the elements in the array)
[DataContract]
public class MoreInfo
{
[DataMember]
public DateTime date { get; set; }
[DataMember]
public string dl_link { get; set; }
...
}
And then try to deserialize the JSON string to a List<MoreInfo>:
JsonConverter.DeserializeObject<List<MoreInfo>>(json)
You will then have to modify the rest of your code to work with MoreInfo objects and not strings in an array.
REFER TO THIS ANSWER
See this question, the accepted answer should help you solve your problem: Json.NET: Deserialization with list of objects

Related

Compare JSON array and JSON object: Cannot convert Array to String error

I am trying to compare json value and based on that i want to update the existing value,for example, currently we have "value" : [r0] in json, i want to compare and if value : [r0] ,then update it to [r0,r1] but iam hiting error that it cannot compare and there is a cast issue, could someone suggest what could be done
public void updateJsonParameter(string file)
{
try
{
var list = new List<string> { "joe", "test" };
JArray array = new JArray(list);
var jobject = JObject.Parse(file);
var ringvalue = (string)jobject["properties"]["parameters"]["ringValue"]["value"]; // unable to case here and compare
jobject["properties"]["parameters"]["ringValue"]["value"] = array; // able to update value but i want to update after comparing the existing values
var result = JsonConvert.SerializeObject(jobject);
}
following is the json format
{
"properties": {
"displayName": "jayatestdefid",
"description": "test assignment through API",
"metadata": {
"assignedBy": "xyz#gmail.com"
},
"policyDefinitionId": "/providers/Microsoft.Management/managementgroups/MGTest/providers/Microsoft.Authorization/policyDefinitions/test",
"parameters": {
"ringValue": {
"value": ["r0"]
}
},
"enforcementMode": "DoNotEnforce",
}
}
jobject.properties.parameters.ringValue.value is an array ["r0"] with one element "r0". If you want to check if it's an array with one element and that element is "r0", do exactly that:
var ringvalue = jobject["properties"]["parameters"]["ringValue"]["value"];
if(ringvalue.length == 1 && ringvalue[0] == "r0")
jobject["properties"]["parameters"]["ringValue"]["value"] = array;
You could compare the ringvalue (which is an JArray) using JArray.DeepEquals and then replace if the comparison returns true. For example,
var list = new List<string> { "joe", "test" };
JArray array = new JArray(list);
JArray valueToCompare = new JArray(new[]{"r0"});
var ringvalue = (JArray)jobject["properties"]["parameters"]["ringValue"]["value"];
if(JArray.DeepEquals(ringvalue,valueToCompare))
{
jobject["properties"]["parameters"]["ringValue"]["value"] = array;
}
First, as Klaycon said in his answer, it's worth noting that your "value" is not a single string. In json, whenever you see [ and ] then you have a collection, or an array, or a list.
When I work with json strings, I always like to be able to convert them into a strongly typed object. There is a very handy online tool I use all the time: http://json2csharp.com/
I took your json string that you provided and pasted it into that website. Here is that your object(s) look like when converted into c# classes:
public class RootObject // You can name this whatever you want
{
public Properties properties { get; set; }
}
public class Metadata
{
public string assignedBy { get; set; }
}
public class RingValue
{
public List<string> value { get; set; }
}
public class Parameters
{
public RingValue ringValue { get; set; }
}
public class Properties
{
public string displayName { get; set; }
public string description { get; set; }
public Metadata metadata { get; set; }
public string policyDefinitionId { get; set; }
public Parameters parameters { get; set; }
public string enforcementMode { get; set; }
}
Now, we can easily do the logic you need as follows:
// This is your json string, escaped and turned into a single string:
string file = "{ \"properties\": { \"displayName\": \"jayatestdefid\", \"description\": \"test assignment through API\", \"metadata\": { \"assignedBy\": \"xyz#gmail.com\" }, \"policyDefinitionId\": \"/providers/Microsoft.Management/managementgroups/MGTest/providers/Microsoft.Authorization/policyDefinitions/test\", \"parameters\": { \"ringValue\": { \"value\": [\"r0\"] } }, \"enforcementMode\": \"DoNotEnforce\", }}";
// Convert your json string into an instance of the RootObject class
RootObject jobject = JsonConvert.DeserializeObject<RootObject>(file);
// Get a list of all the "values"
List<string> values = jobject.properties.parameters.ringValue.value;
// Loop over your colleciton of "value" and do your logic
for (int i = 0; i < values.Count; ++i)
{
if (values[i] == "r0")
{
values[i] = "r0,r1";
}
}
// And finally, turn your object back into a json string
var result = JsonConvert.SerializeObject(jobject);
And this is the final result:
{
"properties":{
"displayName":"jayatestdefid",
"description":"test assignment through API",
"metadata":{
"assignedBy":"xyz#gmail.com"
},
"policyDefinitionId":"/providers/Microsoft.Management/managementgroups/MGTest/providers/Microsoft.Authorization/policyDefinitions/test",
"parameters":{
"ringValue":{
"value":[
"r0,r1"
]
}
},
"enforcementMode":"DoNotEnforce"
}
}

How to define variable in class to receive either List<string> or string when deserializing JSON?

Is there a way to declare a class where for a specific variable I can receive either a List or a string?
I trying to deserialize a JSON and it can come in one of the formats below:
"MercadoriasPresencaCarga": {
"Mercadoria": 7693066,
"Descarga": "08/07/2017 13:35:39"
},
or
"MercadoriasPresencaCarga": {
"Mercadoria": [
"7693066"
],
"Descarga": [
"08/07/2017 13:35:39"
]
},
The class for this block is created like this:
public class MercadoriasPresencaCarga
{
public List<string> Mercadoria { get; set; }
public List<string> Descarga { get; set; }
}
The problem is that if this block of JSON come as the first format that I showed where it is not a array, it will cause an error on it deserialization.
How could I solve this problem?
Ideally the json should always come in the same format, but if that's not a possibility there are some workarounds.
Both json strings will deserialize successfully using the following class:
public class Model
{
// other properties here
// ....
[JsonIgnore]
public string Mercadoria => GetValue("Mercadoria");
[JsonIgnore]
public string Descarga => GetValue("Descarga");
public JObject MercadoriasPresencaCarga { get; set; }
private string GetValue(string path)
{
if (MercadoriasPresencaCarga == null)
{
return null;
}
string value = null;
JToken token = MercadoriasPresencaCarga.SelectToken(path);
if (token.Type == JTokenType.Array && token.HasValues)
{
value = token.First.Value<string>();
}
else
{
value = token.Value<string>();
}
return value;
}
}
Please note that:
MercadoriasPresencaCarga will be deserialized as JObject
Both Mercadoria and Descarga are non-serializable properties (marked with [JsonIgnore])
Testing the code - json string with string properties (no arrays):
string json1 = #"{
""MercadoriasPresencaCarga"": {
""Mercadoria"": 7693066,
""Descarga"": ""08/07/2017 13:35:39""
}
}";
Model model1 = JsonConvert.DeserializeObject<Model>(json1);
Console.WriteLine($"Descarga: {model1.Descarga}, Mercadoria: {model1.Mercadoria}");
Testing the code - json string with arrays:
string json2 = #"{
""MercadoriasPresencaCarga"": {
""Mercadoria"": [
""7693066""
],
""Descarga"": [
""08/07/2017 13:35:39""
]
}
}";
Model model2 = JsonConvert.DeserializeObject<Model>(json2);
Console.WriteLine($"Descarga: {model2.Descarga}, Mercadoria: {model2.Mercadoria}");

c# Converting json string with list of objects to a c# object

I'm tring to convert a string json to c# object,
I've already read several replies in here regarding to similar questions but none of the solutions worked.
This is the json obj
{
"Customer": {
"data_0": {
"id": "273714",
"FirstName": "Zuzana",
"LastName": "Martinkova"
},
"data_1": {
"id": "274581",
"FirstName": "Ricardo",
"LastName": "Lambrechts"
},
"data_2": {
"id": "275190",
"FirstName": "Daniel",
"LastName": "Mojapelo"
},
"data_3": {
"id": "278031",
"FirstName": "Sulochana",
"LastName": "Chandran"
}
}
}
I created the following objects according to the json obj
public class Customer
{
public List<Data> Customers{ get; set; }
public Customer()
{
Customers = new List<Data>();
}
}
public class Data
{
public string id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
As for my code I made a small console app example with all the solotions I found here
static void Main(string[] args)
{
try
{
string jsonString = File.ReadAllText(ConfigurationSettings.AppSettings["filepath"].ToString());
//solution 1
JObject jsonone = JObject.Parse(jsonString);
var collection_one = jsonone.ToObject<Customer>();
//solution 2
JavaScriptSerializer serializer = new JavaScriptSerializer();
var collection_two = serializer.Deserialize<Customer>(jsonString);
//solution 2
var collection_three = JsonConvert.DeserializeObject<Customer> (jsonString);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message); ;
}
Console.ReadKey();
}
Ths json string I get from a 3rd party webservice so just for the example I'm reading the json from a txt file,
the jsonString param value after reading is:
"{\"Customer\":{\"data_0\":{\"id\":\"273714\",\"FirstName\":\"Zuzana\",\"LastName\":\"Martinkova\"},\"data_1\":{\"id\":\"274581\",\"FirstName\":\"Ricardo\",\"LastName\":\"Lambrechts\"},\"data_2\":{\"id\":\"275190\",\"FirstName\":\"Daniel\",\"LastName\":\"Mojapelo\"},\"data_3\":{\"id\":\"278031\",\"FirstName\":\"Sulochana\",\"LastName\":\"Chandran\"}}}"
On every solution I make the collections count is 0, data objects are not including inside the list.
Can someone put some light on it and tell me what is wrong?
Thanks in advance
Your JSON is a Dictionary<string, Data>, not a List<Data>. In addition to that your property is called "Customer", not "Customers". To solve this you need to change a couple things:
public class Customer
{
//JsonProperty is Used to serialize as a different property then your property name
[JsonProperty(PropertyName = "Customer")]
public Dictionary<string, Data> CustomerDictionary { get; set; }
}
public class Data
{
public string Id { get; set; } //You should make this "Id" not "id"
public string FirstName { get; set; }
public string LastName { get; set; }
}
With these class definitions you can easily use the JsonConvert.DeserializeObject() and JsonConvert.SerializeObject() methods:
Customer customer = JsonConvert.DeserializeObject<Customer>(json);
string newJson = JsonConvert.SerializeObject(customer);
I made a fiddle here to demonstrate.
You can try this one.
Add empty class
public class Customer : Dictionary<string, Data>{} //empty class
And the update your existing code
//solution 1
JObject jsonone = JObject.Parse(jsonString);
//Add this line
var token = jsonone.SelectToken("Customer").ToString();
//solution 2 - update jsonString to token variable created above.
var collection_three = JsonConvert.DeserializeObject<Customer>(token);

Creating a JSON string, if the left-hand varaible has dashes in

I am trying to create a json string to send via a httprequest, I have json string like so:
{
"a-string": "123",
"another-string": "hello",
"another": "1"
}
My problem is, if I try and generate it like so
string json = new JavaScriptSerializer().Serialize(new
{
"a-string" = "123",
"another-string" = "hello",
"another" = "1"
});
Leads to:
So what is a way of trying to do the above, without getting that error?
Use Json NewtonSoft NuGet package. Then use my answer here to create a C# class for you json. Since your json has names in them which are not allowed as property names in C#, you can use the JsonPropety attribute so it can use it during serialization. Here is all of the code:
public class Rootobject
{
[JsonProperty("a-string")]
public string astring { get; set; }
[JsonProperty("another-string")]
public string anotherstring { get; set; }
public string another { get; set; }
}
public class Program
{
public static void Main()
{
var root = new Rootobject { another = "1", anotherstring = "hello", astring = "123" };
string json = JsonConvert.SerializeObject(root);
Console.Read();
}
}

How do deserialize JSON with non-standard (and varying) property names (in .NET)

I have to read a JSON stream (which I have no control over), which is in the form:
{"files":
{
"/some_file_path.ext": {"size":"1000", "data":"xxx", "data2":"yyy"},
"/other_file_path.ext": {"size":"2000", "data":"xxx", "data2":"yyy"},
"/another_file_path.ext": {"size":"3000", "data":"xxx", "data2":"yyy"},
}
}
So, I have an object named files, which has a number of properties, which have 1) different names every time, 2) different number of them every time, and 3) names with characters which can't be used in C# properties.
How do I deserialize this?
I'm putting this into a Portable Library, so I can't use the JavaScriptSerializer, in System.Web.Script.Serialization, and I'm not sure about JSON.NET. I was hoping to use the standard DataContractJsonSerializer.
UPDATE: I've changed the sample data to be closer to the actual data, and corrected the JSON syntax in the area the wasn't important. (Still simplified quite a bit, but the other parts are fairly standard)
You can model your "files" object as a Dictionary keyed by the JSON property name:
public class RootObject
{
public Dictionary<string, PathData> files { get; set; }
}
public class PathData
{
public int size { get; set; }
public string data { get; set; }
public string data2 { get; set; }
}
Then, only if you are using .Net 4.5 or later, you can deserialize using DataContractJsonSerializer, but you must first set DataContractJsonSerializerSettings.UseSimpleDictionaryFormat = true:
var settings = new DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true };
var root = DataContractJsonSerializerHelper.GetObject<RootObject>(jsonString, settings);
With the helper method:
public static class DataContractJsonSerializerHelper
{
public static T GetObject<T>(string json, DataContractJsonSerializer serializer = null)
{
using (var stream = GenerateStreamFromString(json))
{
var obj = (serializer ?? new DataContractJsonSerializer(typeof(T))).ReadObject(stream);
return (T)obj;
}
}
public static T GetObject<T>(string json, DataContractJsonSerializerSettings settings)
{
return GetObject<T>(json, new DataContractJsonSerializer(typeof(T), settings));
}
private static MemoryStream GenerateStreamFromString(string value)
{
return new MemoryStream(Encoding.Unicode.GetBytes(value ?? ""));
}
}
Alternatively, you can install Json.NET and do:
var root = JsonConvert.DeserializeObject<RootObject>(jsonString);
Json.NET automatically serializes dictionaries to JSON objects without needing to change settings.
We need to first convert this Invalid JSON to a Valid JSON. So a Valid JSON should look like this
{
"files":
{
"FilePath" : "C:\\some\\file\\path",
"FileData" : {
"size": 1000,
"data": "xxx",
"data2": "yyy"
},
"FilePath" :"C:\\other\\file\\path",
"FileData" : {
"size": 2000,
"data": "xxx",
"data2": "yyy"
},
"FilePath" :"C:\\another\\file\\path",
"FileData" : {
"size": 3000,
"data": "xxx",
"data2": "yyy"
}
}
}
To make it a valid JSON we might use some string functions to make it looks like above. Such as
MyJSON = MyJSON.Replace("\\", "\\\\");
MyJSON = MyJSON.Replace("files", "\"files\"");
MyJSON = MyJSON.Replace("data:", "\"data:\"");
MyJSON = MyJSON.Replace("data2", "\"data2\"");
MyJSON = MyJSON.Replace(": {size", ",\"FileData\" : {\"size\"");
MyJSON = MyJSON.Replace("C:", "\"FilePath\" :\"C:");
Than we can create a class like below to read the
public class FileData
{
public int size { get; set; }
public string data { get; set; }
public string data2 { get; set; }
}
public class Files
{
public string FilePath { get; set; }
public FileData FileData { get; set; }
}
public class RootObject
{
public Files files { get; set; }
}
Assuming you have a valid JSON you could use JavaScriptSerializer to return a list of objects
string json = "{}"
var serializer = new JavaScriptSerializer();
var deserializedValues = (Dictionary<string, object>)serializer.Deserialize(json, typeof(object));
Alternatively you could specify Dictionary<string, List<string>> as the type argument
strign json = "{}";
JavaScriptSerializer serializer = new JavaScriptSerializer();
var deserializedValues = serializer.Deserialize<Dictionary<string, List<string>>>(json);
foreach (KeyValuePair<string, List<string>> kvp in deserializedValues)
{
Console.WriteLine(kvp.Key + ": " + string.Join(",", kvp.Value));
}

Categories

Resources