comma delimited vs list in elasticsearch - c#

I have a nested type with array property,
class MyType
{
public string Name{ get; set; }
public List<OtherType> Others { get; set; }
}
class OtherType
{
public string Title { get; set; }
public List<string> Tags { get; set; } // vs what follows
// public string Tags { get; set; } // eg. = "tag1, tag2, etc"
}
what would normally be the best way to go ( list vs comma separated tags)? which will allow me for easier search?

You can go for nested object with property "include_in_parent" true so that you can use normal queries as well as co-related queries on nest object efficiently.
{ "MyType": {
"properties": {
"name": {
"type": "string"
},
"OtherType": {
"type": "nested",
"include_in_parent": true,
"properties": {
"Title": {
"type": "string"
},
"Tags": {
"type": "string"
}
}
}
} } }

Related

Bind appsettings.json array section to generic class with generic list property

I have to read some values from appsettings.json using IOptionsSnapshot and return them through the API endpoint
"adConfig": [
{
"id": 3,
"adDef": [
{
"type": "number",
"key": "somekey",
"displayName": "Rules",
"values": [
0,
1
],
"regex": null
},
{
"type": "select",
"key": "anotherkey",
"displayName": "Some state",
"values": [
"some string value",
"another string value"
],
"regex": null
}
]
},
{
"id": 1
....
}
]
For this porpose I created 2 classes to use to bind the settings.
public class AdDataModel<T>
{
public string type { get; set; }
public string key{ get; set; }
public string displayName { get; set; }
public List<T> Values { get; set; }
public string regex { get; set; }
}
public class AdConfigurationModel
{
public int Id{ get; set; }
public List<AdDataModel<dynamic>> AdDefinition { get; set; }
}
In the Startup.cs I use this code to bind the settings to the classes:
services.Configure<List<AdConfigurationModel>>(Configuration.GetSection("adConfig"));
So far so good. I inject this into the Controller class but the problem is that AdDataModel.Values are aways of type object<string> ( which is not the case for the first element of adDef:Values subsection). Is there any way to achive Values to be from type int or string based on the values in appsettings.json?
Thanks!

c# nested json to object (current with json.net)

i am new to c# and json.net.
I have a json configuration file and try to parse it to objects. But how can i map the relations correctly in the objects?
Currently the property in project loop is null.
And can the objects map "automatically" without mapping each property name/value?
I can also change the json!
configuration.json:
{
"debug": true,
"log": "database",
"projects": [
{
"name": "Name 1",
"showInfo": false,
"ranges": [
[
5,
6
],
[
9,
10
],
[
15,
20
]
],
"additional": [
{
"name": "subName 1",
"parameter": "ID"
},
{
"name": "subName 2",
"parameter": "ID2"
}
]
},
{
"name": "Name 2",
"showInfo": false,
"ranges": [
[
99,
100
]
]
},
{
"name": "Name 3",
"showInfo": false,
"ranges": [
[
44,
45
]
]
},
{
"name": "Name 4",
"showInfo": false,
"ranges": [
[
12,
14
]
],
"additional": [
{
"name": "subName xy",
"parameter": "ID"
}
]
}
]
}
my try to parse:
Configuration configuration = new Configuration();
JObject jObject = JObject.Parse(File.ReadAllText(filePath));
if (jObject.ContainsKey("debug"))
{
configuration.Debug = (bool) jObject["debug"];
}
if (jObject.ContainsKey("log"))
{
configuration.Log = (string) jObject["log"];
}
//loop projects
JToken projects = jObject["projects"];
foreach (JToken child in projects.Children())
{
var property = child as JProperty;
if (property != null)
{
var test = property.Name;
var test2 = property.Value;
}
}
the objects:
public class Configuration
{
public bool Debug { get; set; } = false;
public string Log { get; set; }
// this is propably wrong
public Dictionary<string, Dictionary<string, Project>> Projects { get; set; }
}
public class Project
{
public string name { get; set; }
public bool showInfo{ get; set; }
// wrong?
public int[,] ranges { get; set; }
// wrong?
public Additional[] Additional{ get; set; }
}
public class Additional
{
public string Name{ get; set; }
public string Parameter { get; set; }
}
You don't need a JObject at all json files can be desterilized to objects it's much more efficient because you don't create unneeded objects.
You Config class is just wrong
public class Configuration
{
public bool Debug { get; set; }
public string Log { get; set; }
public Project[] Projects { get; set; }
}
public class Project
{
public string Name { get; set; }
public bool ShowInfo { get; set; }
public int[][] Ranges { get; set; }
public Additional[] Additional { get; set; }
}
public class Additional
{
public string Name { get; set; }
public string Parameter { get; set; }
}`
Should look like this.
And then use. JsonConvert.DeserializeObject<Configuration>(json); To get the object.
If you have Visual studio it has this cool feature called paste special where you can just past your json and it will create a proper class for deserialization. It's under Edit-> Paste special-> Paste json as class

C# Web API Nested JSON from Stored Procedure in MSSQL

Overview:
I'm building an API using ASP.NET Web API 2. I'm building Stored Procedures in SQL and linking these in the API to serve data.
I know that SQL can return JSON using FOR JSON AUTO, for example. But, I don't think it's the best place to configure the data and out put JSON. So I'm assuming there must be a way to achieve nested JSON in the API.
This is what I want to achieve:
{
"Apps": [
{
"ItemID": "1",
"Path": "/AppReport",
"Name": "AppReport",
"Reports": [
{
"Reports_ItemID": "11",
"Reports_Path": "/AppReport/SubReport",
"Reports_Name": "SubReport"
},
{
"Reports_ItemID": "12",
"Reports_Path": "/AppReport/SubReport2",
"Reports_Name": "SubReport2"
}
]
},
{
"ItemID": "2",
"Path": "/AppReport2",
"Name": "AppReport2",
"Reports": [
{
"Reports_ItemID": "22",
"Reports_Path": "/AppReport/SubReport",
"Reports_Name": "SubReport"
}
]
}
]
}
At the moment it's coming out as a flat Array of Objects
{
"Apps": [
{
"ItemID": "1",
"Path": "/AppReport",
"Name": "AppReport",
"Reports_ItemID": "11",
"Reports_Path": "/AppReport/SubReport",
"Reports_Name": "SubReport"
},
{
"ItemID": "1",
"Path": "/AppReport",
"Name": "AppReport",
"Reports_ItemID": "12",
"Reports_Path": "/AppReport/SubReport2",
"Reports_Name": "SubReport2"
},
...
]
}
I have a class of the Stored Procedure in the API that looks like this:
namespace API.Stored_Procedures
{
public partial class SP_GetApps
{
public System.Guid ItemID { get; set; }
public string Path { get; set; }
public string Name { get; set; }
public System.Guid Report_ItemID { get; set; }
public string Report_Path { get; set; }
public string Report_Name { get; set; }
}
}
My Controller looks like this:
[HttpGet]
[Route("{uid}", Name ="getReportApps")]
[ResponseType(typeof(SP_GetApps_Result))]
public IHttpActionResult SP_GetApps(string uid)
{
var res = db.Database.SqlQuery<SP_GetApps_Result>
("SP_GetApps {0}", uid);
return Ok(res);
}
In order to achieve the desired JSON Class should look like
public class App
{
public string ItemID { get; set; }
public string Path { get; set; }
public string Name { get; set; }
public List<Report> Reports { get; set; }
}
public class Report
{
public string Reports_ItemID { get; set; }
public string Reports_Path { get; set; }
public string Reports_Name { get; set; }
}

Patching an object with an array of objects

I have a many-to-many relationship between Courses and Students for a school. Here's is what I have for a Course:
public class Course
{
public Guid CourseId { get; set; }
public string Name { get; set; }
public ICollection<CourseStudent> Students { get; set; }
}
public class CourseStudent
{
public Guid CourseId { get; set; }
public Guid StudentId { get; set; }
}
I'm using JsonPatch to PATCH my objects. I'm trying to add to the collection of Students, just to the end of the collection with this:
[
{
"op": "add",
"path": "/Students/-",
"value": [
{
"CourseId": "07264DC9-9FEB-42E2-B1EF-08D58F58C873",
"StudentId": "FB6E6988-4A56-4CA4-86E2-E23090FAD98F"
}
]
}
]
But when I submit this, I get an exception saying:
"ClassName": "Microsoft.AspNetCore.JsonPatch.Exceptions.JsonPatchException",
"Message": "The value '[\r\n {\r\n \"CourseId\": \"07264DC9-9FEB-42E2-B1EF-08D58F58C873\",\r\n \"StudentId\": \"FB6E6988-4A56-4CA4-86E2-E23090FAD98F\"\r\n }\r\n]' is invalid for target location.",
The structure looks correct to me based on the Json Patch docs. Any idea why it won't accept my format?
Ended up figuring it out, the format should be:
[
{
"op": "add",
"path": "/Students/-",
"value":
{
"CourseId": "07264DC9-9FEB-42E2-B1EF-08D58F58C873",
"StudentId": "FB6E6988-4A56-4CA4-86E2-E23090FAD98F"
}
}
]

How do I configure services when I bind an array of objects?

I have a json string attached to the VCAP_SERVICES environment variable that looks like this:
{
"redislabs": [
{
"credentials": {
"host": "redis-1756.pcfredissb2.com",
"ip_list": [
"10.999.46.999"
],
"password": "cz(2u",
"port": 1756
},
"syslog_drain_url": null,
"volume_mounts": [],
"label": "redislabs",
"provider": null,
"plan": "simple-redis",
"name": "sdsredis2",
"tags": [
"redislabs"
]
},
{
"credentials": {
"host": "redis-13610.pcfredis.com",
"ip_list": [
"10.999.46.9999"
],
"password": "n-C*",
"port": 13610
},
"syslog_drain_url": null,
"volume_mounts": [],
"label": "redislabs",
"provider": null,
"plan": "simple-redis",
"name": "sdsredis",
"tags": [
"redislabs"
]
}
]
}
In ConfigureServices in Startup.cs, when I run Configuration.GetSection("redislabs").AsEnumerable() I get something that looks like this:
I have a few options classes that looks like this:
public class RedisLabs
{
public RedisLab[] redislabs { get; set; }
}
public class RedisLab
{
public Credentials credentials { get; set; }
public object syslog_drain_url { get; set; }
public object[] volume_mounts { get; set; }
public string label { get; set; }
public object provider { get; set; }
public string plan { get; set; }
public string name { get; set; }
public string[] tags { get; set; }
}
public class Credentials
{
public string host { get; set; }
public string[] ip_list { get; set; }
public string password { get; set; }
public int port { get; set; }
}
My question is how the heck do I perform the binding on something like this? Is binding an array of objects even possible?
I've tried:
var redislabs = new List<RedisLab>();
Configuration.GetSection("redislabs").Bind(redislabs);
and
services.Configure<RedisLabs>(Configuration);
and a few other methods. Nothing seems to work.
Halp, plz.
Given your json file and classes this should work (binding top level section to instance of a class that that holds the array):
var redisLabs = new RedisLabs();
Configuration.Bind(redisLabs);
This also works:
services.Configure<RedisLabs>(Configuration);
...
var rlOptions = app.ApplicationServices.GetRequiredService<IOptions<RedisLabs>>();
var redisLabs = rlOptions.Value;

Categories