I have this JSON:
{
"ID":123,
"Products":null,
"Title":"Products"
}
I want to add some data from DB to the "Products" node so my final json will look like so:
{
"ID":123,
"Products":[
{
"ID":1,
"Name":"AA"
},
{
"ID":2,
"Name":"BB"
}
],
"Title":"Products"
}
I'm using this code:
internal class Product
{
public int ID { get; set; }
public string Name { get; set; }
}
//simulate DB
var products= new List<Product>()
{
new Product() {ID=1,Name="AA" },
new Product() {ID=2,Name="BB" }
};
string JSONstr = FilesUtils.OpenFile(Path.Combine(Environment.CurrentDirectory, "Sample.json"));
JObject JSON = JObject.Parse(JSONstr);
((JValue)JSON["Products"]).Value = JObject.FromObject(products);
But I get an exception:
Object serialized to Array. JObject instance expected.
You can do:
JSON["Products"] = JToken.FromObject(products);
To add a new property, do the same thing, e.g.:
JSON["TimeStamp"] = JToken.FromObject(DateTime.UtcNow);
Notes:
The item setter for JObject will add or replace the property with the specified name "Products".
JToken.FromObject() serializes any .Net object to a LINQ to JSON hierarchy. JToken is the abstract base class of this hierarchy and so can represent both arrays, objects, and primitives. See here for details.
Sample fiddle.
The expected object will have to be (according to your JSON). If that's the JSON you want you might consider wrapping it up and adding the ID and a Title as shown in the JSON.
public class Product
{
public int ID { get; set; }
public string Name { get; set; }
}
public class YourObject
{
public int ID { get; set; }
public List<Product> Products { get; set; }
public string Title { get; set; }
}
Related
I've got the following json document:
{
"name": "bert",
"Bikes": {
"Bike1": {
"value": 1000,
"type": "Trek"
},
"Bike2": {
"value": 2000,
"type": "Canyon"
}
}
}
With potentially other bikes like Bike3...BikeN. I want to deserialize to C# objects. Problem is that in the deserialization step the bikes data is completely lost, resulting in a null Bikes collection.
Code to reproduce:
[Test]
public void FirstCityJsonParsingTest()
{
var file = #"./testdata/test.json";
var json = File.ReadAllText(file);
var res = JsonConvert.DeserializeObject<Person>(json);
Assert.IsTrue(res.Name == "bert");
// next line is failing, because res.Bikes is null...
Assert.IsTrue(res.Bikes.Count == 2);
}
public class Bike
{
public string Id { get; set; }
public int Value { get; set; }
public string Type { get; set; }
}
public class Person
{
public string Name { get; set; }
public List<Bike> Bikes { get; set; }
}
To fix this problem a change in the used model is necessary. But what change is needed here to fill the bikes data correctly?
Note: Changing the input document is not an option (as it's a spec)
Your code structure is not reflecting your json. Common approach to deserializing json with dynamic property names is to use Dictionary<string, ...> (supported both by Json.NET and System.Text.Json). Try the following:
public class Bike
{
public int Value { get; set; }
public string Type { get; set; }
}
public class Person
{
public string Id { get; set; }
public string Name { get; set; }
public Dictionary<string, Bike> Bikes { get; set; }
}
Person.Bikes should be changed to Dictionary<string, Bike> (also Bike.Id property is not needed) cause Bikes json element is not an array but object.
i have this json string:
{"products": [{"id": 22,"date_add": "2021-06-17 19:21:26","date_upd": "2021-07-12 13:02:01","name": [{"id": "1","value": "Product 1"}, {"id": "2", "value": "Product 1"}]}}, {"id": 1,"date_add": "2021-06-17 18:54:54","date_upd": "2021-06-17 18:54:54","name": [{"id": "1","value": "something321"},{"id": "2","value": "something23"}]}]}
and this class:
class Products
{
[JsonProperty("id")]
public override string ExternalId { get; set; }
[JsonProperty("name")]
public Dictionary<string, string> Name { get; set; }
[JsonProperty("date_upd")]
public DateTime DateModified{ get; set; }
}
i want to map my json products to List of Products, so I tried this:
// get "products" array from json
Regex regex = new Regex(#"(?:{""products"":)(.+)(?:})");
MatchCollection matches = regex.Matches(result);
if (matches.Count > 0)
{
result = matches[0].Groups[1].Value;
}
else
{
result = null;
}
//
var deserialized = JsonConvert.DeserializeObject<List<PrestaProducts>>(result);
it throws: Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'System.Collections.Generic.Dictionary`2[System.String,System.String]' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly. ...
ok - if i set type of name to object, it works correct and set the list of anon objs.
( public object Name { get; set; } )
but how can i set that names to dictionary?
What I see from your example, you cannot convert name to Dictionary<string, string> since it's array.
However you can do something like this. Change this line to include List:
var deserialized = JsonConvert.DeserializeObject<List<Products>>(result);
and change your model to something like this:
public class Products
{
[JsonProperty("id")]
public string ExternalId { get; set; }
[JsonProperty("name")]
public List<Dictionary<string, string>> Name { get; set; }
[JsonProperty("date_upd")]
public DateTime DateModified { get; set; }
}
I don't know if this is what you expected or wanted but at least you will fix the error you have at the moment.
To me it does not make much sense to have dictionary inside list but you cannot directly convert array to dictionary in a way you tried.
You can convert it to list products
var jsonObj = JsonConvert.DeserializeObject<JsonObjects>(json);
var productObjects = jsonObj.products;
if you want to convert it to dictionary, try this:
var products = new Products { products = new List<Product> { } };
foreach (var item in productObjects)
{
var product = new Product
{
id = item.id,
date_add = item.date_add,
date_upd = item.date_upd,
name=new Dictionary<string,string>()
};
foreach (var name in item.name)
{
product.name.Add(name.id,name.value);
}
products.products.Add(product);
}
var productsJson= JsonConvert.SerializeObject( products);
OUTPUT
{"products":[
{"id":22,"date_add":"2021-06-17 19:21:26","date_upd":"2021-07-12 13:02:01",
"name":{"1":"Product 1","2":"Product 1"}},
{"id":1,"date_add":"2021-06-17 18:54:54","date_upd":"2021-06-17 18:54:54",
"name":{"1":"Hummingbird printed t-shirt","2":"Hummingbird printed t-shirt"}}
]}
classes
public class Name
{
public string id { get; set; }
public string value { get; set; }
}
public class JsonProduct
{
public int id { get; set; }
public string date_add { get; set; }
public string date_upd { get; set; }
public List<Name> name { get; set; }
}
public class JsonObjects
{
public List<JsonProduct> products { get; set; }
}
public class Product
{
public int id { get; set; }
public string date_add { get; set; }
public string date_upd { get; set; }
public Dictionary<string, string> name { get; set; }
}
public class Products
{
public List<Product> products { get; set; }
}
I've got the following json document:
{
"name": "bert",
"Bikes": {
"Bike1": {
"value": 1000,
"type": "Trek"
},
"Bike2": {
"value": 2000,
"type": "Canyon"
}
}
}
With potentially other bikes like Bike3...BikeN. I want to deserialize to C# objects. Problem is that in the deserialization step the bikes data is completely lost, resulting in a null Bikes collection.
Code to reproduce:
[Test]
public void FirstCityJsonParsingTest()
{
var file = #"./testdata/test.json";
var json = File.ReadAllText(file);
var res = JsonConvert.DeserializeObject<Person>(json);
Assert.IsTrue(res.Name == "bert");
// next line is failing, because res.Bikes is null...
Assert.IsTrue(res.Bikes.Count == 2);
}
public class Bike
{
public string Id { get; set; }
public int Value { get; set; }
public string Type { get; set; }
}
public class Person
{
public string Name { get; set; }
public List<Bike> Bikes { get; set; }
}
To fix this problem a change in the used model is necessary. But what change is needed here to fill the bikes data correctly?
Note: Changing the input document is not an option (as it's a spec)
Your code structure is not reflecting your json. Common approach to deserializing json with dynamic property names is to use Dictionary<string, ...> (supported both by Json.NET and System.Text.Json). Try the following:
public class Bike
{
public int Value { get; set; }
public string Type { get; set; }
}
public class Person
{
public string Id { get; set; }
public string Name { get; set; }
public Dictionary<string, Bike> Bikes { get; set; }
}
Person.Bikes should be changed to Dictionary<string, Bike> (also Bike.Id property is not needed) cause Bikes json element is not an array but object.
I am new to C# need help to convert json Object to Array
convert this json
[
{
"Id": 1000,
"Name": "May",
"Address": "odyssey",
"Country": "USA",
"Phone": "12345"
}
]
To
var details = {1000,May,odyssey,USA,12345};
Use Newtonsoft.Json to deserialize JSON to a specified .net type. You can deserialize to a class too, see below:
public class Person
{
public int Id {get;set;}
public string Name {get;set;}
public string Address {get;set;}
public string Country {get;set;}
public string Phone {get;set;}
}
var details = JsonConvert.DeserializeObject<Person>(json);
You are going to have to deserialize the Json String. Deserialize into array of objects.
JavaScriptSerializer js = new JavaScriptSerializer();
yourClass[] items = js.Deserialize<Yourclass[]>(yourJSONcontent);
Steps:
1. Create Model.
2. Get Data in string
3.Deserialize Object
And if you are confused How to create C# model from the json then use this link.
https://app.quicktype.io
Use This Model.
public class Test
{
[JsonProperty("Id")]
public long Id { get; set; }
[JsonProperty("Name")]
public string Name { get; set; }
[JsonProperty("Address")]
public string Address { get; set; }
[JsonProperty("Country")]
public string Country { get; set; }
[JsonProperty("Phone")]
[JsonConverter(typeof(ParseStringConverter))]
public long Phone { get; set; }
}
string data="Your Json String"
var details = JsonConvert.DeserializeObject<Test>(data);
To make a list from your json values you can use a JObject, you don't have to know the objects stored in your Json in contrary to the others question.
JObject myObject = JsonConvert.DeserializeObject<JObject>(myJson);
List<object> myList = new List<object>();
foreach (var element in myObject)
{
myList.Add(element.Value);
}
If you already know what your json is made of, you can create a class that represent your object and implement the interface IEnumerable.
var myObject = JsonConvert.DeserializeObject<MyClass>(myJson);
var myArray = myObject2.ToArray():
public class MyClass
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Country { get; set; }
public int Phone { get; set; }
public object[] ToArray()
{
return new object[]
{
Id,
Name,
Address,
Country,
Phone
};
}
}
NB : the variable myJson in the previous codes is a string that represent your json as var myJson = "{\"Id\": 1000,\"Name\": \"May\",\"Address\": \"odyssey\",\"Country\": \"USA\",\"Phone\": \"12345\"}";
I'm using the code below for serialization.
var json = JsonConvert.SerializeObject(new { summary = summary });
summary is a custom object of type SplunkDataModel:
public class SplunkDataModel
{
public SplunkDataModel() {}
public string Category { get; set; }
public int FailureCount { get; set; }
public Dictionary<string, SplunkError> FailureEntity { get; set; }
public Dictionary<string, string> JobInfo { get; set; }
public string JobStatus { get; set; }
public int SuccessCount { get; set; }
public List<string> SuccessEntity { get; set; }
public int TotalCount { get; set; }
}
Serialization results in the JSON below:
{
"summary": {
"Category": "category",
"JobStatus": "Failure",
"JobInfo": {
"Course processing failed": ""
},
"TotalCount": 0,
"SuccessCount": 0,
"FailureCount": 0,
"FailureEntity": {},
"SuccessEntity": []
}
}
Now, for unit testing purposes, I need to deserialize it, but the code below is returning an object with empty values. Where am I going wrong?
var deserialized = JsonConvert.DeserializeObject<SplunkDataModel>(contents);
On my side, it was because I had no public setter for my properties.
Instead of having
public class MyClass
{
public int FileId { get; }
}
I should have
public class MyClass
{
public int FileId { get; set; }
}
silly mistake that cost me hours....
When you serialized your SplunkDataModel to JSON, you wrapped it in an object with a summary property. Hence, when you deserialize the JSON back to objects, you need to use the same structure. There are several ways to go about it; they all achieve the same result.
Declare a class to represent the root level of the JSON and deserialize into that:
public class RootObject
{
public SplunkDataModel Summary { get; set; }
}
Then:
var deserialized = JsonConvert.DeserializeObject<RootObject>(contents).Summary;
Or, deserialize by example to an instance of an anonymous type, then retrieve your object from the result:
var anonExample = new { summary = new SplunkDataModel() };
var deserialized = JsonConvert.DeserializeAnonymousType(contents, anonExample).summary;
Or, deserialize to a JObject, then materialize your object from that:
JObject obj = JObject.Parse(contents);
var deserialized = obj["summary"].ToObject<SplunkDataModel>();