How can I parse instance properties by using json data? - c#

I try to parse json data to List<Employee> instance. But I don't want to use Json-to-C# tool for creating a shadow from json pattern. I want to take values only. Maybe I can use keys to take values (Employee). I want to fill a List of Employee.
My Json:
{
"type":"SUCCESS",
"msg":"Container RBFFiyatlama2_1.0.1 successfully called.",
"result":{
"execution-results":{
"results":[
{
"value":2,
"key":""
},
{
"value":{
"com.myteam.rbffiyatlama2.Employee":{
"salary":2400.0,
"age":35,
"cofactor":0.2
}
},
"key":"Employee0"
},
{
"value":{
"com.myteam.rbffiyatlama2.Employee":{
"salary":4800.0,
"age":35,
"cofactor":0.2
}
},
"key":"Employee1"
}
],
"facts":[
{
"value":{
"org.drools.core.common.DefaultFactHandle":{
"external-form":"0:88:1504512052:1504512052:160:DEFAULT:NON_TRAIT:com.myteam.rbffiyatlama2.Employee"
}
},
"key":"Employee0"
},
{
"value":{
"org.drools.core.common.DefaultFactHandle":{
"external-form":"0:89:213603577:213603577:159:DEFAULT:NON_TRAIT:com.myteam.rbffiyatlama2.Employee"
}
},
"key":"Employee1"
}
]
}
}
}
How can I fill Employee without creating any C# class by using above json.
public class Employee
{
public int age { get; set; }
public double cofactor { get; set; }
public int salary { get; set; }
}

You could use dynamics. The following should do what you're after and it's all native:
string jsonString = YourGetJsonStringMethod();
List<Employee> employees = new List<Employee>();
dynamic data = System.Web.Helpers.Json.Decode(jsonString);
dynamic results = data["result"]["execution-results"]["results"];
if (results.Length > 1)
{
for (var i = 1; i < results.Length; i++)
{
var dynamicEmployee = results[i]["value"]["com.myteam.rbffiyatlama2.Employee"];
dynamicEmployee["salary"] = (int) dynamicEmployee["salary"];
var encoded = System.Web.Helpers.Json.Encode(dynamicEmployee);
employees.Add(System.Web.Helpers.Json.Decode<Employee>(encoded));
}
}
You will obviously need to include System.Web.Helpers in your references, which you can find under Assemblies > Extensions in your Visual Studio Reference Manager.
Bear in mind that this code may raise an exception when you're debugging. If so, refer to this question for the solution.
This code "just works". I will leave it to you to do validation, null-checking and exception catching.

Related

Get values out of collections with FastMember

I use FastMember to get values out of objects and nested objects. If a property is a string or int everything works fine. But now I want to get the values also for collections. Here is my code so far:
// Set accessor
var sourceAccessor = ObjectAccessor.Create(source);
if (sourceAccessor.Target.GetType().GetInterface(nameof(ICollection)) != null || sourceAccessor.Target.GetType().GetInterface(nameof(IEnumerable)) != null)
{
foreach (/* idk */)
{
// READ & RETURN VALUES HERE
}
}
An object could look like this:
{
Id: 1,
Surname: Doe,
Prename: John,
Professions: [
{ Name: ab },
{ Name: xy }
]
}
Which means professions would result in a problem.
Any advise how I can solve this problem? Thanks!
It's not obvious from the question what the data type of the source variable is, but you should just be able to check if the value returned by the accessor implements IEnumerable or not and act accordingly.
Here's a quick worked example that iterates over the Professions property of a 'Person' object and just dumps the ToString() representation to the console - if you wanted to dive into each Profession object using FastMember you could construct another ObjectAccessor to do it, I guess - it's not clear what your goal is once you're iterating.
The same tactic will work if you're building the ObjectAccessor directly from an array - you just check if the accessor.Target is IEnumerable and cast-and-iterate in a similar fashion.
class Program
{
static void Main(string[] args)
{
var p = new Person
{
Professions = new List<Profession>
{
new Profession("Joker"),
new Profession("Smoker"),
new Profession("Midnight toker")
}
};
var accessor = ObjectAccessor.Create(p);
var professions = accessor[nameof(Person.Professions)];
if (professions is IEnumerable)
{
foreach (var profession in (IEnumerable)professions)
{
Console.WriteLine(profession);
}
}
}
}
class Person
{
public List<Profession> Professions { get; set; }
}
class Profession
{
public string Name { get; set; }
public Profession( string name)
{
Name = name;
}
public override string ToString()
{
return Name;
}
}

How to select an element's value from a JArray

I'm having a bit of trouble with C# (VS 2017, .Net 4.6) code. It'd be great if someone could help. I have a JSON file:
{
"makerCommission": 10,
"takerCommission": 10,
"buyerCommission": 0,
"updateTime": 1540015045989,
"balances": [
{
"asset": "BTC",
"free": "0.22222222",
"locked": "0.00000000"
},
{
"asset": "LTC",
"free": "2.00000000",
"locked": "3.00000000"
},
{
"asset": "ETH",
"free": "4.00000000",
"locked": "5.00000000"
}
]
}
I would like to retrieve the "free" value of any coin using:
result = (dynamic)JArray.Parse(MyData)
I do not want to retrieve all free values. How can I get 0.22222222, if I pick BTC?
First of all, your overall JSON does not represent an array, it represents an object which contains an array. So you would need to use JObject.Parse instead of JArray.Parse.
You can use the following LINQ-to-JSON code to find a specific asset in the array and then get the free value from it:
JObject obj = JObject.Parse(json); // Parse the JSON to a JObject
string free = obj["balances"] // Navigate down to the "balances" array
.Where(jt => (string)jt["asset"] == "BTC") // Find the object(s) containing the asset you want
.Select(jt => (string)jt["free"]) // From those get the "free" value
.FirstOrDefault(); // Take the first of those
Fiddle: https://dotnetfiddle.net/uFjSib
You are almost there. You have a JSON object, that contains the array, so you need to parse first the Object and then access the array using the name balances.
var result = (dynamic)JObject.Parse(MyData);
Console.WriteLine(result.balances); // output JArray ...
You can then get the value from the array like this:
Console.WriteLine(String.Format("{0} - {1}", result.balances[2].asset, result.balances[2].free));
The output is the third element from the array:
ETH - 4.00000000
In order to get only the BTC entry you need to filter the array:
foreach (var balance in result.balances)
{
if (balance.asset == "BTC")
{
Console.WriteLine(balance.free);
}
}
A better approach would be to create a class that represents the object structure and parse it. The filtering then will be easier using LINQ:
public class BalanceItem
{
public string asset { get; set; }
public double free { get; set; }
public double locked { get; set; }
}
public class Items
{
public List<BalanceItem> balances { get; set; }
}
var items = JsonConvert.DeserializeObject<Items>(MyData);
var btc = items.balances.FirstOrDefault (b => b.asset == "BTC");
if (btc != null)
{
Console.WriteLine(btc.free);
}
The output is: 0.22222222
Alternatively, you could use JToken
The following script gives you the wanted value. Maybe not the conceptually finest approach, but really intuitive.
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class Program
{
public static void Main()
{
string json = #"
{
""makerCommission"": 10,
""takerCommission"": 10,
""buyerCommission"": 0,
""updateTime"": 1540015045989,
""balances"": [
{
""asset"": ""BTC"",
""free"": ""0.22222222"",
""locked"": ""0.00000000""
},
{
""asset"": ""LTC"",
""free"": ""2.00000000"",
""locked"": ""3.00000000""
},
{
""asset"": ""ETH"",
""free"": ""4.00000000"",
""locked"": ""5.00000000""
}
]
}";
var value = "";
JToken token = JToken.Parse(json);
var balances = token.SelectToken("balances");
foreach(var balance in balances){
if((string)balance.SelectToken("asset") == "BTC"){
value = (string)balance.SelectToken("free");
}
}
Console.WriteLine("value: " + value);
}
}
Inspired by this post

Change status value from int to string

I have a status property with int values in array of objects. Below is the output of array of objects.
[
{
"enterpriseServiceId": 1,
"enterpriseServices": {},
"status": 3,
"id": 1,
"createdOn": "2017-12-29T17:58:15.4855946",
"createdBy": "System",
"modifiedOn": "2017-12-29T17:58:15.4855946",
"modifiedBy": "System"
},
{
"enterpriseServiceId": 2,
"enterpriseServices": {},
"status": 1,
"id": 2,
"createdOn": "2017-12-29T17:58:15.4855946",
"createdBy": "System",
"modifiedOn": "2017-12-29T17:58:15.4855946",
"modifiedBy": "System"
}
]
The status property is enum value type. I am trying to convert that to string value so it is easier to read when it is returned in output.
Below is my code that gets the data from sql server database.
ENUM
namespace CoreLibrary.Models.Enums
{
public static class Common
{
public enum Status
{
Active = 1,
InActive,
Completed,
Failed,
InProgress,
Pause,
Resume,
Skip,
Running
}
}
}
Entity Model:
namespace CoreLibrary.Models.Entities
{
public class Deployments : BaseProperties
{
public int EnterpriseServiceId { get; set; }
[ForeignKey("EnterpriseServiceId")]
public virtual EnterpriseServices EnterpriseServices { get; set; }
public Common.Status Status { get; set; }
}
}
Method that retrieves data from database:
[HttpGet("~/api/Deployments/GetWithJoins")]
public JsonResult GetWithJoins()
{
try
{
// includeList for including data from external tables (JOIN Query)
var includeList = new List<Expression<Func<Deployments, object>>>();
includeList.Add(d => d.EnterpriseServices);
IEnumerable<Deployments> result = _repository.GetByIdWithJoins(queryable: includeList).ToList();
return Json(result);
}
catch (Exception ex)
{
var innerException = ex.InnerException == null ? null : ex.InnerException.Message.ToString();
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(new { status = "failed", message = ex.Message.ToString(), innerException = innerException });
}
}
The result variable returns the output I shared at very beginning of this post. I am trying to convert status to return string value instead of int.
I am not sure if thats even possible or it is the right way to output of status int to string value?
I tried online, but I havent found a solution to my requirement. I would appreciate any help you guys can give. :)
When we call JSON(someObject), ASP.NET uses its JavaScriptSerializer to create a JsonResult. The default configuration of the JavaScriptSerializer converts enums to their integer representation.
We can configure the serializer to use a string representation of enums instead. There are details on how to do that here: JSON serialization of enum as string
If that approach does not appeal, then you can use LINQ to map to an anonymous object using Enum.ToString(). Here is an example:
var result = deployments.Select(x =>
{
return new
{
Status = x.Status.ToString(),
x.EnterpriseServiceId
};
});
While the LINQ approach will work, it might lead to maintenance problems in the long-term.

How to update a nested document in a mongodb with c#

I hope someone can help me to understand how I can update a document in a mongodb.
My problem is that i have a document which contains an array. And in this array there are objects with a specific ID(like you would find in sql database). Now I want to update the data inside those objects if they have the searched id.
A document looks like this
{
"_id": "63dafa72f21d48312d8ca405",
"tasks": [{
"_ref": "63d8d8d01beb0b606314e322",
"data": {
"values": [{
"key": "Deadline",
"value": "2014-10-13"
}]
}
}, {
"_ref": "84dd046c6695e32322d842f5",
"data": {
"values": []
}
}]
}
I did write the method updateProject
public bool updateProject(Project pro, Project dbPro)
{
var collection = db.GetCollection<BsonDocument>("projects");
var filter = Builders<BsonDocument>.Filter.Eq("_id", dbPro.Id);
var update = Builders<BsonDocument>.Update.Set("tasks", pro.Tasks);
var result = collection.UpdateOne(filter, update);
if (result.IsModifiedCountAvailable)
{
if (result.ModifiedCount == 1)
{
return true;
}
}
return false;
}
And thats how a project does look like in c#.
class Project{
public string id;
public List<Task> Tasks;
}
class Task{
public string id;
public List<Value> Values;
}
class Value{
public String key;
public String value;
}
but i cant figure out how i can go deeper to find the searched id.

Using JArray for serializing data from database in WebAPI (C#)

I want to achieve the following JSON data:
[
{
"name":"Deutschland",
"code":"de"
},
{
"name":"Frankreich",
"code":"fr"
},
{
"name":"Japan",
"code":"jpn"
}
]
Currently I'm getting this result of JSON data:
{
"groups":[
{
"name":"Deutschland",
"code":"de"
},
{
"name":"Frankreich",
"code":"fr"
},
{
"name":"Japan",
"code":"jpn"
}
]
}
Here is the code of the Controller:
public dynamic GetGroups()
{
JObject o = JObject.FromObject(new
{
groups = from g in db.QR_Groups
select new
{
name = g.name,
code = g.code
}
});
return o;
/*Here I've tried to get JSON data as array without the Property "groups"*/
//JArray a = new JArray(
// from g in db.QR_Groups
// select new JValue(g));
//return a;
}
Can anyone tell me how to retrieve the JSON data as per the first JSON example above?
And is the type "dynamic" good practice for the method?
First of all there is no need to do serialization manually. ASP.Net WebApi MediaFormatters are going to take care of it based on the Request Content-Type. So Create a class as shown below.
public class Group
{
public string name { get; set; }
public string code { get; set; }
}
Then your Web API endpoint should be -
[HttpGet]
public HttpResponseMessage GetCountries()
{
List<Group> groups = (from g in db.QR_Groups
select new Group
{
name = g.name,
code = g.code
}).ToList();
return Request.CreateResponse(HttpStatusCode.OK, groups);
}
And when I make a Fiddler request, I was able to get the output which you are interested -
Try this one:
var json = JsonConvert.SerializeObject(from g in db.QR_Groups
select new
{
name = g.name,
code = g.code
});
And is the type "dynamic" good practice for the method?
no, it's not best practise. Better one is to create new class

Categories