The JSON data is as follows:
{"Sucess":true,
"Code":0,
"Msg":"Sucess",
"Data":{
"UserDayRanking":
{
"UserID":11452112,
"UserCharm":0,
"UserName":"gay",
"UserGender":1,
"UserLevel":36,
"UserPhoto":"http://res.xxx.com/2020/3/16/63719926625601201487545U11452112.jpeg",
"Ranking":0,
"IsNobility":0,
"NobilityType":0,
"NobilityLevel":0,
"UserShowStyle":null,
"LiveLevelUrl":null,
"IsStealth":false},
"DayRankingList":[
{
"UserID":3974854,
"UserCharm":114858,
"UserName":"jack",
"UserGender":1,
"UserLevel":91,
"UserPhoto":"http://res.xxx.com/2020/2/15/63717400601924412312384U3974854.jpeg",
"Ranking":2,
"IsNobility":1,
"NobilityType":1,
"NobilityLevel":3,
"UserShowStyle":
{
"NameColor":100102,
"BorderColor":100403,
"LiangMedal":0,
"DztCountDown":0,
"Mounts":100204,
"LiveLevelCode":0,
"LiveRights":null
},
"LiveLevelUrl":null,
"IsStealth":false
},
{"UserID":6231512,
"UserCharm":22644,
"UserName":"red.girl",
"UserGender":1,
"UserLevel":57,
"UserPhoto":"http://res.xxx.com/2019/11/20/63709843050801519858823U6231512.jpeg",
"Ranking":3,
"IsNobility":0,
"NobilityType":0,
"NobilityLevel":0,
"UserShowStyle":{
"NameColor":0,
"BorderColor":0,
"LiangMedal":0,
"DztCountDown":0,
"Mounts":0,
"LiveLevelCode":0,
"LiveRights":null
},
"LiveLevelUrl":null,
"IsStealth":false}
],
"LiveCharmSwitch":1,
"IsSelf":false
}
}
I want to use c # extraction
"UserID": 3974854,
"UserCharm": 114858,
"UserName": "jack",
"UserID":6231512,
"UserCharm":22644,
"UserName":"red.girl",
That is to extract UserID, UserCharm, UserName,This json has many layers,
What I want after the extraction is,id is sorted in order
id = 1, UserID = 3974854, UserCharm = 114858, UserName = jack
id = 2, UserID = 6231512, UserCharm = 22644, UserName = red.girl
I use the following code, but only extract the first one
string json = #"{"Sucess":true,"Code":0,"Msg":"Sucess","Data":{"UserDayRanking":{"UserID":11452112,"UserCharm":0,"UserName":"gay","UserGender":1,"UserLevel":36,"UserPhoto":"http://res.xxx.com/2020/3/16/63719926625601201487545U11452112.jpeg","Ranking":0,"IsNobility":0,"NobilityType":0,"NobilityLevel":0,"UserShowStyle":null,"LiveLevelUrl":null,"IsStealth":false},"DayRankingList":[{"UserID":3974854,"UserCharm":114858,"UserName":"jack","UserGender":1,"UserLevel":91,"UserPhoto":"http://res.xxx.com/2020/2/15/63717400601924412312384U3974854.jpeg","Ranking":2,"IsNobility":1,"NobilityType":1,"NobilityLevel":3,"UserShowStyle":{"NameColor":100102,"BorderColor":100403,"LiangMedal":0,"DztCountDown":0,"Mounts":100204,"LiveLevelCode":0,"LiveRights":null},"LiveLevelUrl":null,"IsStealth":false},{"UserID":6231512,"UserCharm":22644,"UserName":"red.girl","UserGender":1,"UserLevel":57,"UserPhoto":"http://res.xxx.com/2019/11/20/63709843050801519858823U6231512.jpeg","Ranking":3,"IsNobility":0,"NobilityType":0,"NobilityLevel":0,"UserShowStyle":{"NameColor":0,"BorderColor":0,"LiangMedal":0,"DztCountDown":0,"Mounts":0,"LiveLevelCode":0,"LiveRights":null},"LiveLevelUrl":null,"IsStealth":false}],"LiveCharmSwitch":1,"IsSelf":false}}";
List<Info> jobInfoList = JsonConvert.DeserializeObject<List<Info>>(z);
foreach (Info jobInfo in jobInfoList)
{
//Console.WriteLine("UserName:" + jobInfo.UserName);
}
public class Info
{
public string UserCharm { get; set; }
public string UserName { get; set; }
public data DayRankingList { get; set; }
}
public class data
{
public int UserID { get; set; }
public string UserCharm { get; set; }
public string UserName { get; set; }
public string UserGender { get; set; }
public string UserLevel { get; set; }
}
The above code only shows username = jack,Never show username = red.girl
As it looks to me then you want some details from your JSON has the which is in DayRankingList. As you only want some data then we can use a tool like http://json2csharp.com/ to create our classes and then remove what we don't need. Then we end up with the following classes.
public class DayRankingList
{
public int UserID { get; set; }
public int UserCharm { get; set; }
public string UserName { get; set; }
}
public class Data
{
public List<DayRankingList> DayRankingList { get; set; }
}
public class RootObject
{
public Data Data { get; set; }
}
Which you can deserialise like this
string json = .....
var root = JsonConvert.DeserializeObject<RootObject>(json);
Then if you wish, you can extract the inner data into a new List<> and then just work on that.
List<DayRankingList> rankingLists = root.Data.DayRankingList;
//Do something with this, such as output it
foreach(DayRankingList drl in rankingLists)
{
Console.WriteLine(String.Format("UserId {0} UserCharm {1} UserName {2}",drl.UserId, drl.UserCharm, drl.UserName));
}
You can use Json.Linq to parse your JSON into JObject and enumerate DayRankingList items (since it's an array). Then convert every item into data class and order the result sequence by UserID
var jObject = JObject.Parse(json);
var rankingList = (jObject["Data"] as JObject)?.Property("DayRankingList");
var list = rankingList.Value
.Select(rank => rank.ToObject<data>())
.OrderBy(item => item?.UserID);
foreach (var user in list)
Console.WriteLine($"{user.UserID} {user.UserName}");
Another way is copy your JSON, go to Edit->Paste Special->Paste JSON as classes menu in Visual Studio and generate a proper class hierarchy (I've got 5 classes, they are quite long to post here), then use them during deserialization
The most type-safe way is to define the class structure that you want, like jason.kaisersmith suggested.
To have the final format you need, though, you might want to do an extra Linq Order and Select, to include the id:
var finalList = rankingLists.OrderBy(rl => rl.UserId).Select((value, index) => new
{
id = index,
value.UserId,
value.UserCharm,
value.UserName
});
foreach (var drl in finalList)
{
Console.WriteLine($"Id = {drl.id}, UserId = {drl.UserId}, UserCharm = {drl.UserCharm}, UserName = {drl.UserName}");
}
I am working with a huge JSON file, where is just needed to extract some fields inside it. I've been searching some ways to deserialize, but don't want to create the whole Class and Object in C# with all the fields inside the JSON, this would be a lot of useless memory.
I can get the JSON file using a Webclient:
using (WebClient wc = new WebClient())
{
jsonWeb = wc.DownloadString("http://link_to_get_JSON");
}
//Deserialize into a JObject
JObject obj = JObject.Parse(jsonWeb);
//Tried to access the info with
var val = obj.PropTwo;
var solution = obj.Descendants().OfType<JProperty>().Where(p => p.Name == "solverSolution").Select(x => x.Value.ToString()).ToArray();
I really could not find a way to get the wanted fields inside the JObject.
Inside the JSON, the only information is needed is the solverSolution:{} below:
{
"content":
[
{
"id":"f4d7e7f5-86ab-4155-8336-ca5f552cb3b4",
"name":"m1",
"description":"m1",
"maxHeight":2000.0,
"layers":6,
"pallet":{},
"product":{},
"solverSolution":
{
"id":"106ef605-d95e-4c74-851b-63310fbcbc7d",
"name":"solver",
"maxHeight":2000.0,
"layers":6,
"solution":[
{
"X1":0,
"Y1":0,
"Z1":0,
"X2":296,
"Y2":246,
"Z2":220
},
...
"default":false
},
"customSolutions":[0]
},
{},
...
],
"pageable":{},
"totalPages":1,
"last":true,
"totalElements":7,
"first":true,
"sort":{},
"number":0,
"numberOfElements":7,
"size":20
}
Here I leave my appreciation and gratitude for the community beforehand. Cheers,
André Castro.
Then use only the desired properties in your object, making sure to follow the structure of the desired model.
public partial class RootObject {
[JsonProperty("content")]
public Content[] Content { get; set; }
}
public partial class Content {
[JsonProperty("solverSolution")]
public SolverSolution SolverSolution { get; set; }
}
public partial class SolverSolution {
[JsonProperty("id")]
public Guid Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("maxHeight")]
public double MaxHeight { get; set; }
[JsonProperty("layers")]
public long Layers { get; set; }
[JsonProperty("solution")]
public Solution[] Solution { get; set; }
[JsonProperty("default")]
public bool Default { get; set; }
}
public partial class Solution {
[JsonProperty("X1")]
public long X1 { get; set; }
[JsonProperty("Y1")]
public long Y1 { get; set; }
[JsonProperty("Z1")]
public long Z1 { get; set; }
[JsonProperty("X2")]
public long X2 { get; set; }
[JsonProperty("Y2")]
public long Y2 { get; set; }
[JsonProperty("Z2")]
public long Z2 { get; set; }
}
The parser will ignore the rest that do not map to properties of the object model.
var root = Jsonsonvert.DeserializeObject<RootObject>(jsonWeb);
var solverSolution = root.Content[0].SolverSolution;
How can I get all SolverSolution
SolverSolution[] solutions = root.Content.Select(content => content.SolverSolution).ToArray();
I use:
JsonConvert.DeserializeObject<dynamic>(stringInput)
to get anonymouse type I need
Then you can use something like this to get specific part:
var obj = JsonConvert.DeserializeObject<dynamic>(input)["content"][0]["solverSolution"];
It's easy and gets me job done.
Edit:
Side note, please next time when you upload json just cut off parts that are not needed so I can serialize it, took me some time to fix it :D
You can use a JObject to parse all Json. Then, you can map a specific children to your object.
Reference
I am attempting to write a code that finds objects in MongoDB collection with Linq.
Here's my code:
class Program
{
static void Main(string[] args)
{
var client = new MongoClient();
var db = client.GetDatabase("SoundsDB");
var collection = db.GetCollection<Sound>("SoundsCollection");
string myID = "0vvyXSoSHI";
var myObjects = collection
.Find(b => b.objectId == myID);
}
}
public class Sound
{
public string _id { get; set; }
public Result[] results { get; set; }
}
public class Result
{
public Audio_File audio_file { get; set; }
public DateTime createdAt { get; set; }
public string location { get; set; }
public string objectId { get; set; }
public DateTime updatedAt { get; set; }
}
public class Audio_File
{
public string __type { get; set; }
public string name { get; set; }
public string url { get; set; }
}
Here's the JSON in my MongoDB collection:
{
"_id" : ObjectId("56acced71b8ac8702446e8c6"),
"results" : [
{
"audio_file" : {
"__type" : "File",
"name" : "tfss-3c489351-0338-4903-8d94-a0f0c7091ef9-hi.m4a",
"url" : "http://files.parsetfss.com/hithere.m4a"
},
"createdAt" : "2014-12-27T22:59:04.349Z",
"location" : "Home",
"objectId" : "0vvyXSoSHI",
"updatedAt" : "2015-02-26T22:48:02.264Z"
}
]
}
I am trying to make it work but in the following line:
.Find(b => b.objectId == myID)
I get this error:
Cannot convert lambda expression to type 'MongoDB.Driver.FilterDefinition' because it is not a delegate type
Any idea how can I fix it and be able to search through the JSON for objects using their objectId?
Thanks!
I think the problem is that you are searching for a sub-document, not the main doc. Try this:
var myObjects = collection
.Find(b => b.results.Any(r=>r.objectId == myID));
Also - make sure that the objectId value is actually a string in your collection. It seems like it's a string in the object model but an objectId in the db. You may need to (a) change your object model and (b) change that query so that you are asking for r.objectId == ObjectId.Parse(myID) instead of the way I wrote it.
c# MongoDb .Find is Async
If you're using the c# drivers, you probably also need to implement async for this call:
static void Main() {
MainAsync().Wait();
}
static async Task MainAsync() {
var client = new MongoClient();
var db = client.GetDatabase("SoundsDB");
var collection = db.GetCollection<Sound>("SoundsCollection");
string myID = "0vvyXSoSHI";
var myObjects = await collection
.Find(b => b.objectId == myID).ToListAsync();
}
This way, you are using find, and converting the results to a list (so, myObjects will be a List<SoundsCollection> object).
My data is having following structure
public enum ParamType
{
Integer=1,
String=2,
Boolean=3,
Double=4
}
public class Gateway
{
public int _id { get; set; }
public string SerialNumber { get; set; }
public List<Device> Devices { get; set; }
}
public class Device
{
public string DeviceName { get; set; }
public List<Parameter> Parameters { get; set; }
}
public class Parameter
{
public string ParamName { get; set; }
public ParamType ParamType { get; set; }
public string Value { get; set; }
}
I filled 10 document objects of Gateway in a MongoDB database.
Now I want to query all those gateways which contains a device having Parameter with ParamName as "Target Temperature" and whose Value > 15.
I created following queries
var parameterQuery = Query.And(Query<Parameter>.EQ(p => p.ParamName, "Target Temperature"), Query<Parameter>.GT(p => int.Parse(p.Value), 15));
var deviceQuery = Query<Device>.ElemMatch(d => d.Parameters, builder => parameterQuery);
var finalQuery = Query<Gateway>.ElemMatch(g => g.Devices, builder => deviceQuery);
But when I run this, it is giving an exception
Unable to determine the serialization information for the expression: (Parameter p) => Int32.Parse(p.Value)
Please suggest where I am wrong.
As the error suggests, you can't use Int32.Parse inside your query. This lambda expression is used to get out the name of the property and it doesn't understand what Int32.Parse is.
If you are querying a string, you need to use a string value for comparison:
var parameterQuery = Query.And(Query<Parameter>.EQ(p => p.ParamName, "Target Temperature"), Query<Parameter>.GT(p => p.Value, "15"));
However, that's probably not what you want to do since you're using GT. To be treated as a number for this comparison you need the value to actually be an int in mongo, so you would need to change the type of your property:
public class Parameter
{
public string ParamName { get; set; }
public ParamType ParamType { get; set; }
public int Value { get; set; }
}
var parameterQuery = Query.And(Query<Parameter>.EQ(p => p.ParamName, "Target Temperature"), Query<Parameter>.GT(p => p.Value, 15));
Summary
I ran into this when I was modifying a list. It appears that Linq First/FirstOrDefault was not handled well by MongoDB for me. I changed to be an array index var update = Builders<Movie>.Update.Set(movie => movie.Movies[0].MovieName, "Star Wars: A New Hope"); Note: This is in Asp.Net 5 using MongoDB.Driver 2.2.0.
Full Example
public static void TypedUpdateExample() {
var client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("test");
var collection = database.GetCollection<Movie>("samples");
//Create some sample data
var movies = new Movie {
Name = "TJ",
Movies = new List<MovieData>
{
new MovieData {
MovieName = "Star Wars: The force awakens"
}
}
};
collection.InsertOne(movies);
//create a filter to retreive the sample data
var filter = Builders<Movie>.Filter.Eq("_id", movies.Id);
//var update = Builders<Movie>.Update.Set("name", "A Different Name");
//TODO:LP:TSTUDE:Check for empty movies
var update = Builders<Movie>.Update.Set(movie => movie.Movies[0].MovieName, "Star Wars: A New Hope");
collection.UpdateOne(filter, update);
}
public class Movie {
[BsonId]
public ObjectId Id { get; set; }
public string Name { get; set; }
public List<MovieData> Movies { get; set; }
}
public class MovieData {
[BsonId]
public ObjectId Id { get; set; }
public string MovieName { get; set; }
}
I have the following objects:
public class DomainStudent {
public long Id { get; set; }
public string AdvisorId { get; set; }
}
public class ApiStudent {
public long Id { get; set; }
public long AdvisorName { get; set; }
}
When I run the following mapping:
ApiStudent api = new ApiStudent();
api.Id = 123;
api.AdvisorName = "Homer Simpson";
DomainStudent existing = service.load(api.Id); // 123
// at this point existing.AdvisorId = 555
existing = Mapper.Map<ApiStudent, DomainStudent>(api);
// at this point existing.AdvisorId = null
How can I configure AutoMapper such that when the property AdvisorId is missing from the source object, so that it does not get overwritten to null?
You must change the Map() call to:
Mapper.Map(api, existing);
and then configure the mapping to:
Mapper.CreateMap<ApiStudent, DomainStudent>()
.ForMember(dest => dest.AdvisorId, opt => opt.Ignore());