Iterating over a JSON object (NOT an array) in C# - c#

So, I have a json file in the following format
{
"-KeArK3V02mXYWx2OMWh" : {
"Description" : "this is a description",
"Location" : "Atlanta",
"Name" : "Event One",
"Time" : "2017-03-01T21:53:12.924645Z"
},
"-KeAtCNF_rmewZ_U3PpH" : {
"Description" : "another description",
"Location" : "Charlotte",
"Name" : "Event Two",
"Time" : "2017-03-01T22:01:25.603547Z"
},
"-KeAtd8CQW_EfH3Sw4YQ" : {
"Description" : "description goes here",
"Location" : "Toronto",
"Name" : "Event Three",
"Time" : "2017-03-01T22:03:19.3953859Z"
}
}
and I have a class called Event that is defined as follows
class Event {
public string Description { get; set; }
public string Location { get; set; }
public string Name { get; set; }
public DateTime Time { get; set; }
}
and I'd like to go through this and deserialize each of the child nodes into Event objects, basically deserializing the entire JSON into a List<Event>.
The issue is that the events aren't in an array, they're child nodes of another JSON object. So it turns out it's not as simple as
List<Event> elist = JsonConvert.DeserializeObject<List<Event>>(jsonResult);
I've seen similar questions asked where the items were organized in a JSON array, and I've tried the solutions listed there but they only work when it's an actual array, not the structure I have here. Google Firebase is what I'm working with here and unfortunately it doesn't support JSON arrays, so I have no way of containing the items in an array instead.
I'm not really used to JSON syntax so I might be missing something really obvious here, but I'm completely stumped.
Any help would be greatly appreciated.

Can you try this approach? It's pretty straight forward
var str = #"{
'-KeArK3V02mXYWx2OMWh' : {
'Description' : 'this is a description',
'Location' : 'Atlanta',
'Name' : 'Event One',
'Time' : '2017-03-01T21:53:12.924645Z'
},
'-KeAtCNF_rmewZ_U3PpH' : {
'Description' : 'another description',
'Location' : 'Charlotte',
'Name' : 'Event Two',
'Time' : '2017-03-01T22:01:25.603547Z'
},
'-KeAtd8CQW_EfH3Sw4YQ' : {
'Description' : 'description goes here',
'Location' : 'Toronto',
'Name' : 'Event Three',
'Time' : '2017-03-01T22:03:19.3953859Z'
}
}";
Dictionary<string, Event> elist = JsonConvert.DeserializeObject<Dictionary<string, Event>>(str);

Related

InvalidOperationException: Cannot get the value of a token type 'String' as a number

Trying to get data from products.json file and store it in Products[] mention in file JsonFileProductServices.cs but getting this error
'The JSON value could not be converted to System.Int32. Path: $[0].id | LineNumber: 2 | BytePositionInLine: 33.'
JsonFileProductServices.cs is basically service to fetch data from product.json
Below mention are the files
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text.Json.Serialization;
using System.Text.Json;
namespace DevTest.Website.Models
{
public class Product
{
public int Id { get; set; }
public string Maker { get; set; }
[JsonPropertyName("img")]
public string Image { get; set; }
public string Url { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int[] Ratings { get; set; }
public override string ToString() => JsonSerializer.Serialize<Product>(this);
}
}
---product.cs---
[
{
"id" : "jenlooper-cactus",
"maker" : "#jenlooper",
"img" : "https://user-images.githubusercontent.com/41929050/61567048-13938600-aa33-11e9-9cfd-712191013192.jpeg",
"url" : "https://www.hackster.io/agent-hawking-1/the-quantified-cactus-an-easy-plant-soil-moisture-sensor-e65393",
"title" : "The Quantified Cactus: An Easy Plant Soil Moisture Sensor",
"description" : "This project is a good learning project to get comfortable with soldering and programming an Arduino."
},
{
"id" : "jenlooper-light",
"maker" : "jenlooper",
"img" : "https://user-images.githubusercontent.com/41929050/61567049-13938600-aa33-11e9-9c69-a4184bf8e524.jpeg",
"url" : "https://www.hackster.io/agent-hawking-1/book-light-dee7e4",
"title" : "A beautiful switch-on book light",
"description" : "Use craft items you have around the house, plus two LEDs and a LilyPad battery holder, to create a useful book light for reading in the dark."
},
{
"id" : "jenlooper-lightshow",
"maker" : "#jenlooper",
"img" : "https://user-images.githubusercontent.com/41929050/61567053-13938600-aa33-11e9-9780-104fe4019659.png",
"url" : "https://www.hackster.io/agent-hawking-1/bling-your-laptop-with-an-internet-connected-light-show-30e4db",
"title" : "Bling your Laptop with an Internet-Connected Light Show",
"description" : "Create a web-connected light-strip API controllable from your website, using the Particle.io."
},
{
"id" : "jenlooper-survival",
"maker" : "jenlooper",
"img" : "https://user-images.githubusercontent.com/41929050/61567051-13938600-aa33-11e9-8ae7-0b5c19aafab4.jpeg",
"url" : "https://www.hackster.io/agent-hawking-1/create-a-compact-survival-kit-38bfdb",
"title" : "Create a Compact Survival Kit with LED Track Lighting",
"description" : "Use an Altoids tin with Chibitronics sticker LEDs to create a light-up compact that doubles as a survival kit for the young hipster"
},
{
"id" : "sailorhg-bubblesortpic",
"maker" : "sailorhg",
"img" : "https://user-images.githubusercontent.com/41929050/61567054-13938600-aa33-11e9-9163-eec98e239b7a.png",
"url" : "https://twitter.com/sailorhg/status/1090107740049952770",
"title" : "Bubblesort Visualization",
"description" : "Visualization of sailor scouts sorted by bubblesort algorithm by their planet's distance from the sun"
},
{
"id" : "sailorhg-corsage",
"maker" : "sailorhg",
"img" : "https://user-images.githubusercontent.com/41929050/61567055-142c1c80-aa33-11e9-96ff-9fbac6413625.png",
"url" : "https://twitter.com/sailorhg/status/1090113666911891456",
"title" : "Light-up Corsage",
"description" : "Light-up corsage I made with my summer intern."
},
{
"id" : "sailorhg-kit",
"maker" : "sailorhg",
"img" : "https://user-images.githubusercontent.com/41929050/61567056-142c1c80-aa33-11e9-8682-10065d338145.png",
"url" : "https://twitter.com/sailorhg/status/1090122822007963648",
"title" : "Pastel hardware kit",
"description" : "Pastel hardware kits complete with custom manufactured pastel alligator clips."
},
{
"id" : "sailorhg-led",
"maker" : "sailorhg",
"img" : "https://user-images.githubusercontent.com/41929050/61567052-13938600-aa33-11e9-9a88-cd842073ba44.jpg",
"url" : "https://twitter.com/sailorhg/status/1090117277540745216",
"title" : "Heart-shaped LED",
"description" : "custom molded heart shaped LED with sprinkles."
},
{
"id" : "selinazawacki-soi-shirt",
"maker" : "selinazawacki",
"img" : "https://user-images.githubusercontent.com/41929050/61567060-142c1c80-aa33-11e9-8188-5a4803844a9e.png",
"url" : "https://www.instagram.com/p/BNvESj-j8PI/",
"title" : "Black Sweatshirt",
"description" : "Black sweatshirt hoody with the Sick of the Internet logo."
},
{
"id" : "selinazawacki-soi-pins",
"maker" : "selinazawacki",
"img" : "https://user-images.githubusercontent.com/41929050/61567059-142c1c80-aa33-11e9-939b-2ecf4492786d.png",
"url" : "https://www.instagram.com/p/BNm6hZzDoEF/",
"title" : "Sick of the Internet Pins",
"description" : "Still some time to enter the pin/sticker giveaway! "
},
{
"id" : "vogueandcode-hipster-dev-bro",
"maker" : "vogueandcode",
"img" : "https://user-images.githubusercontent.com/41929050/61567061-14c4b300-aa33-11e9-9fee-63ff2c0c9823.png",
"url" : "https://www.vogueandcode.com/shop/hipster-dev-bro",
"title" : "Hipster Dev",
"description" : "Hipster Dev is busy coding away while styled in a camo jacket and orange beanie."
},
{
"id" : "vogueandcode-pretty-girls-code-tee",
"maker" : "vogueandcode",
"img" : "https://user-images.githubusercontent.com/41929050/61567062-14c4b300-aa33-11e9-9dcd-8bfed4ece810.png",
"url" : "https://www.vogueandcode.com/shop/pretty-girls-code-tee",
"title" : "Pretty Girls Code Tee",
"description" : "Everyone’s favorite design is finally here on a tee! The Pretty Girls Code crew-neck tee is available in a soft pink with red writing."
},
{
"id" : "vogueandcode-ruby-sis-2",
"maker" : "vogueandcode",
"img" : "https://user-images.githubusercontent.com/41929050/61567063-14c4b300-aa33-11e9-8515-bcb866da9ea3.png",
"url" : "https://www.vogueandcode.com/shop/ruby-sis-2",
"title" : "Ruby Sis",
"description" : "Styled in a dashiki, Ruby Sis is listening to music while coding in her favorite language, Ruby!"
},
{
"id" : "selinazawacki-moon",
"maker" : "selinazawacki",
"img" : "https://user-images.githubusercontent.com/41929050/61567057-142c1c80-aa33-11e9-9781-9e442418eaab.png",
"url" : "https://www.instagram.com/p/BFktVYPinKQ/",
"title" : "Holographic Dark Moon Necklace",
"description" : "Not sure if I'll be making more, get it while I have it in the store."
},
{
"id" : "selinazawacki-shirt",
"maker" : "selinazawacki",
"img" : "https://user-images.githubusercontent.com/41929050/61567058-142c1c80-aa33-11e9-89fb-b4f30d84d69d.png",
"url" : "https://www.instagram.com/p/BEXlpiZCnJ3/",
"title" : "Floppy Crop",
"description" : "Used up the Diskette fabric today to make 2 of these crops."
}
]
----products.json
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text.Json.Serialization;
using System.Text.Json;
using Microsoft.AspNetCore.Hosting;
using DevTest.Website.Models;
namespace DevTest.Website.Services
{
public class JsonFileProductService
{
public JsonFileProductService(IWebHostEnvironment webHostEnvironment)
{
WebHostEnvironment = webHostEnvironment;
}
public IWebHostEnvironment WebHostEnvironment { get; }
private string JsonFileName => Path.Combine(WebHostEnvironment.WebRootPath, "data", "products.json");
public IEnumerable<Product> GetProducts()
{
using (var jsonFileReader = File.OpenText(JsonFileName))
{
return JsonSerializer.Deserialize<Product[]>(jsonFileReader.ReadToEnd(),
new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
}
}
}
}
--JsonFileProductService.cs---
How are you going to convert
"id" : "jenlooper-survival",
to this
public class Product
{
public int Id { get; set; }
.....
}
you have to fix the class
public class Product
{
public string Id { get; set; }
.....
}
Hard to tell without any source code but potential problems that can cause this:
Different model/dto when reading vs writing
Data can be serialized as some type T and you try cast it to string or data is as string but you trying to deserialize it to T.
I would compare your json data types to your C# model.
If you using JsonSerializer.Deserialize you can try to use JsonConvert.DeserializeObject from Newtonsoft.Json but I would first try to find difference between your model and json file.

C# MongoDB update object from oplog

What I have is a MongoDB which contains a collection of products. Lets say each product has the following structure:
public ObjectId Id { get; set; }
public string label { get; set; }
public List<IngredientsModel> ingredients { get; set; }
Now my C# program gets notified via the oplog if there was a change. This oplog looks like this:
{
"ts" : Timestamp(1425392023, 1),
"h" : NumberLong("-7452324865462273810"),
"v" : 2,
"op" : "u",
"ns" : "coll.products",
"o2" : { "_id" : ObjectId("54f5b87cd4c6959bd3ecf2d6") },
"o" : { "$set" : { "ingredients.1.ingredid" : "54f5c117d4c6959bd3ecf2e8" } }
}
When my application starts I create a list of products which I get from the MongoDB. I just use products.findAll() and the put them in a List<'products>
I have several clients connected to the MongoDB and every client gets notified via oplog.
Now I want to update my local lists without querying the MongoDB since I have all the information needed to update my local products already in the oplog.
My question is now: How to do that?
My approach is the following:
Deserialize the object to Json
var prodjson= Product[0].ToJson<ProductModel>();
Convert Json to BsonDocument
var prodbson= BsonSerializer.Deserialize<BsonDocument>(prodjson);
Apply the "o" key from the oplog to the prodbson
"o" : { "$set" : { "ingredients.1.ingredid" : "54f5c117d4c6959bd3ecf2e8" } }
NO IDEA

MongoDB - return document references as nested document

imagine this structure:
collection companies:
{
"company" : "foo",
"city" : "1234"
}
{
"company" : "bar",
"city" : "1234"
}
collection cities:
{
"_id" : "1234",
"cityname" : "Berlin",
"zipcode" : "09123"
}
now i want to get as result when i query for company = "foo":
{
"company" : "foo",
"city" : {
"_id" : "1234",
"cityname" : "Berlin",
"zipcode" : "09123"
}
}
How to query this from the C# driver? i have the result structure as C# class and i would like to have it strong-typed.
like this:
MongoCollection<Company> mc = mongodb.GetCollection<Company>("companies")
And the Class company looks like:
public class Company {
public string company {get;set;}
public City city {get;set;}
}
You should get the idea.
The Mongo ducomentation didn't say much about this.
Your are frequently asking the city data by reference, embedding this document makes it faster to query.
Restructure your document schema and embed the city (address) document into the company document.
{
company : "Deutsche Bank",
address : {
street : "Müllerstraße",
number : "34a",
zipcode : "13353",
city : "Berlin"
}
}
If you have no other option because of any business logic is relying on the company document, you could choose to create aggregation queries and project a new document as result.
[additional info]
You have to run an extra query to get the referenced document, foreach every company and embed the city info.

Assign JSON value to property in C#

From an API I receive a JSON-object that looks like this:
{
"wind" : {
"speed" : 7.31,
"deg" : 187.002
},
"rain" : {
"3h" : 0
},
"clouds" : {
"all" : 92
},
"coord" : {
"lon" : 139,
"lat" : 35
},
"dt" : 1369824698,
"id" : 1851632,
"cod" : 200,
"weather" : [
{
"id" : 804,
"main" : "clouds",
"icon" : "04n",
"description" : "overcast clouds"
}
],
"main" : {
"humidity" : 89,
"temp_max" : 292.04,
"temp_min" : 287.04,
"temp" : 289.5,
"pressure" : 1013
},
"sys" : {
"country" : "JP",
"sunrise" : 1369769524,
"sunset" : 1369821049
},
"name" : "Shuzenji"
}
I would like to assign two of these values to my class:
public class Weather {
public string Name { get; set; }
public string Temp { get; set; }
}
The name I can assign like this:
weather.Name = TheJSON.name.ToString();
But the temp is trickier, because it's nested inside the "main"-array. I´ve seen many examples on how to do this in Javascript but not so much in C#. Thanks!
Main is not an array. It is an object, so
TheJSON.main.temp.ToString()
The easiest way to work with JSON data is to deserialize them as C# objects and directly use them in your application. You can use a tool like JSON C# Class Generator to automatically generate the C# class from the JSON data. Once you have your C# classes generated, you can deserialize the JSON string using the JsonConvert.DeserializeObject(jsonText); The generated code requires Newtonsoft Json.NET which you can easily add as a NuGet package.
If you save your JSON content in D:\test.json, you can use the following code to access the values using the C# objects generated. The example below is to just give you an idea on the usage.
var json = File.ReadAllText(#"D:\test.json");
var weather = JsonConvert.DeserializeObject<Weather>(json);
Console.WriteLine(weather.Name);
Console.WriteLine(weather.Sys.Country);

retrieve item from a json file c#

{
"_id": "underscore",
"_rev": "136-824a0ef7436f808755f0712c3acc825f",
"name": "underscore",
"description": "JavaScript's functional programming helper library.",
"dist-tags": {},
"versions": {
"1.0.3": {
"name": "xxx",
"description": "xxx"
},
"1.0.4": {},
"1.1.0": {}
}
}
I would like to retrieve the latest version(1.1.0) from the json file. However, it always gives out me errors of "can not deserialize json object into type RootObject
Here is my class
public class versions
{
public string name { get; set; }
public string description { get; set; }
}
public class RootObject
{
public List<versions> vs { get; set; }
}
And here is where I used it
RootObject[] dataset = JsonConvert.DeserializeObject<RootObject[]>(json);
Any idea. Many thankx
Update:
I have updated the JSON file format, but some problem..
I think the problem is, that in JSON you have to quote all "field"/attribute names. (Thats a difference from standard Javascript-Notation, where you can have unquoted attributes).
So, your file should be like:
{
"_id" : "underscore",
"versions": {
"1.0.3" : {
"name": "xxx",
"description": "xxx"
}
}
Note that {1.0.3: { name: "xxx" } } wouldn't be valid JavaScript either since '1.0.3' is an invalid identifier in JavaScript.
Looking at the JSON in your updated answer:
{
"_id" : "underscore",
"versions": {
"1.0.3" : {
"name": "xxx",
"description": "xxx"
},
"1.0.4" : {
"name": "xxx",
"description": "xxx"
}
}
This is still Invalid JSON - you have 4 opening { and only 3 closing }
you should use http://jsonlint.com/ - to validate your JSON and ensure it is Valid
I've fixed your json in question. Now for your real question
I would like to retrieve the latest version(1.1.0) from the json file. However, it always gives out me errors of "can not deserialize json object into type RootObject
You have property names like 1.0.3 that are unknown at compile time. So you can not deserialize them to a concrete class. You should handle them dynamically.
Try this:
var versions = JObject.Parse(json)["versions"]
.Children()
.Cast<JProperty>()
.ToDictionary(c => c.Name, c => c.Value.ToObject<versions>());

Categories