I am Serializing data from SQL database to JSON, how can I serialize just the values without the string name OR a function to trim the serialized JSON before Deserializing.
I read about ScriptIgnoreAttribute but didn't see how to relate it with what I want to do
Original JSON
[
{
"CODE": "AF",
"TOTALVALUE": "$23,554,857.27"
},
{
"CODE": "AS",
"TOTALVALUE": "$38,379,964.65"
},
{
"CODE": "SG",
"TOTALVALUE": "$24,134,283.47"
}
]
Desired JSON
[
{
"AF": "$23,554,857.27"
},
{
"AS": "$38,379,964.65"
},
{
"SG": "$24,134,283.47"
}
]
SQL View structure
My SQL query to return the data
SELECT [CODE],[TOTALVALUE] FROM [dbo].[vw_BuyersByCountryValue]
enter code here
Code for Serializing in ASP.NET
[WebMethod]
public void GetBuyersByCountryValue()
{
using (PMMCEntities ctx = new PMMCEntities())
{
ctx.Configuration.ProxyCreationEnabled = false;
var qry = ctx.vw_BuyersByCountryValue.ToList();
var js = new JavaScriptSerializer();
string strResponse = js.Serialize(qry);
Context.Response.Clear();
Context.Response.ContentType = "application/json";
Context.Response.AddHeader("content-length", strResponse.Length.ToString(CultureInfo.InvariantCulture));
Context.Response.Flush();
Context.Response.Write(strResponse);
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
}
It is very simple
// data from the query
// SELECT CODE, TOTALVALUE FROM vw_BuyersByCountryValue
var sqldata = new []
{
new { Code = "AF", TotalValue = "$23,554,857.27" },
new { Code = "AS", TotalValue = "$38,379,964.65" },
new { Code = "SG", TotalValue = "$24,134,283.47" },
};
var mappeddata = sqldata.Select( r =>
{
var dict = new Dictionary<string,string>();
dict[r.Code] = r.TotalValue;
return dict;
});
var json = JsonConvert.SerializeObject(mappeddata,Formatting.Indented);
content of json
[
{
"AF": "$23,554,857.27"
},
{
"AS": "$38,379,964.65"
},
{
"SG": "$24,134,283.47"
}
]
.net fiddle sample
You can even populate it as
{
"AF": "$23,554,857.27",
"AS": "$38,379,964.65",
"SG": "$24,134,283.47"
}
with
var sqldata = new []
{
new { Code = "AF", TotalValue = "$23,554,857.27" },
new { Code = "AS", TotalValue = "$38,379,964.65" },
new { Code = "SG", TotalValue = "$24,134,283.47" },
};
var mappeddata = sqldata.ToDictionary(r => r.Code, r => r.TotalValue);
var json = JsonConvert.SerializeObject(mappeddata,Formatting.Indented);
.net fiddle sample
Update
[WebMethod]
public void GetBuyersByCountryValue()
{
using (PMMCEntities ctx = new PMMCEntities())
{
ctx.Configuration.ProxyCreationEnabled = false;
var qry = ctx.vw_BuyersByCountryValue.ToList();
var mapped = qry.Select r =>
{
var dict = new Dictionary<string,string>();
dict[r.CODE] = r.TOTALVALUE;
return dict;
});
string strResponse = Newtonsoft.Json.JsonConvert.SerializeObject(mapped);
Context.Response.Clear();
Context.Response.ContentType = "application/json";
Context.Response.AddHeader("content-length", strResponse.Length.ToString(CultureInfo.InvariantCulture));
Context.Response.Flush();
Context.Response.Write(strResponse);
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
}
You need the NuGet package Newtonsoft.Json
Related
I am trying to send a notification from my backend with the following code:
var obj = new
{
app_id = new Guid(ConfigurationManager.AppSettings["oneSignalAppid"]),
contents = new { en = "English Message"},
headings = new { en = "English heading" },
chrome_web_image = https://pixabay.com/static/img/no_hotlinking.png",
web_buttons = #"[
{
'id': 'like-button',
'text': 'Like',
'icon': 'http://i.imgur.com/N8SN8ZS.png',
'url': 'https://yoursite.com'},
{
'id': 'read-more-button',
'text': 'Read more',
'icon': 'http://i.imgur.com/MIxJp1L.png',
'url': 'https://yoursite.com'
}]",
included_segments = new string[] { "All" }
};
either i get a 400 response or i get my notification without the buttons.
How do i set the web_buttons properly?
the solution is to serialize the array object using anonymous array of anonymous types:
web_buttons = new[] {
new {id="id-1", text= buttonText, url="http://yourDomain.com" },
}
...
var availableToField = Infer.Field<Project>(f => f.Availablity.AvailableTo);
var availableFromField = Infer.Field<Project>(f => f.Availablity.AvailableFrom);
var nameField = Infer.Field<Project>(f => f.Contact.Name);
var active_date_to = new DateRangeQuery(){
Name = "toDate",
Boost = 1.1,
Field = "availablity.availableTo",
GreaterThan = DateTime.Now,
TimeZone = "+01:00",
Format = "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy"
};
var active_date_from = new DateRangeQuery(){
Name = "from",
Boost = 1.1,
Field = "availablity.availableFrom",
LessThanOrEqualTo = DateTime.Now,
TimeZone = "+01:00",
Format = "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy"
};
public ISearchResult<Project> Search(SearchCriteria criteria)
{var ret = _client.Search<Project>(s =>
s.Query(q =>
active_date_from &&
active_date_to &&
q.Match(d => d.Query(criteria.FreeText))
).From(criteria.CurrentPage).Size(criteria.Take)
.From(criteria.CurrentPage)
.Take(criteria.Take)
);
result.Total = ret.Total;
result.Page = criteria.CurrentPage;
result.PerPage = criteria.Take;
result.Results = ret.Documents;
return result;
}
what im trying to do is get the results matching the freetext but are also withing the pricerange..
somehow though what i get is an invalid NEST response build from a unsuccessful low level call on POST... and in consequence an empty query.
there are no compiling errors.
does anyone have an idea where i could have gone wrong or what im missing?
the other thing i tried was
var mustClauses = new List<QueryContainer>();
mustClauses.Add(active_date_from);
mustClauses.Add(active_date_to);
mustClauses.Add(new TermQuery
{
Field = "contact.name",
Value = criteria.FreeText
});
var searchRequest = new SearchRequest<Project>()
{
Size = 10,
From = 0,
Query = new BoolQuery
{
Must = mustClauses
}
};
var ret = _client.Search<Project>(searchRequest);
result.Total = ret.Total;
result.Page = criteria.CurrentPage;
result.PerPage = criteria.Take;
result.Results = ret.Documents;
which got me pretty much the same results.. (read: none)
is there something im missing?
edit:
however.. this:
var ret = _client.Search<Project>(s => s.Query(q => q.Match(m => m.Field(f => f.DisplayName).Query(criteria.FreeText))));
gives me exactly what i want (without the validation of the dates of course and only looking at one field)
In your first example, the match query is missing a field property which is needed for the query. Because of NEST's conditionless query behaviour, the query is not serialized as part of the request. The two date range queries are serialized however.
Here's a simple example that you may find useful to get the correct query you're looking for
void Main()
{
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var defaultIndex = "projects";
var connectionSettings = new ConnectionSettings(pool, new InMemoryConnection())
.DefaultIndex(defaultIndex )
.PrettyJson()
.DisableDirectStreaming()
.OnRequestCompleted(response =>
{
if (response.RequestBodyInBytes != null)
{
Console.WriteLine(
$"{response.HttpMethod} {response.Uri} \n" +
$"{Encoding.UTF8.GetString(response.RequestBodyInBytes)}");
}
else
{
Console.WriteLine($"{response.HttpMethod} {response.Uri}");
}
Console.WriteLine();
if (response.ResponseBodyInBytes != null)
{
Console.WriteLine($"Status: {response.HttpStatusCode}\n" +
$"{Encoding.UTF8.GetString(response.ResponseBodyInBytes)}\n" +
$"{new string('-', 30)}\n");
}
else
{
Console.WriteLine($"Status: {response.HttpStatusCode}\n" +
$"{new string('-', 30)}\n");
}
});
var client = new ElasticClient(connectionSettings);
var availableToField = Infer.Field<Project>(f => f.Availablity.AvailableTo);
var availableFromField = Infer.Field<Project>(f => f.Availablity.AvailableFrom);
var nameField = Infer.Field<Project>(f => f.Contact.Name);
var active_date_to = new DateRangeQuery
{
Name = "toDate",
Boost = 1.1,
Field = availableToField,
GreaterThan = DateTime.Now,
TimeZone = "+01:00",
Format = "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy"
};
var active_date_from = new DateRangeQuery
{
Name = "from",
Boost = 1.1,
Field = availableFromField,
LessThanOrEqualTo = DateTime.Now,
TimeZone = "+01:00",
Format = "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy"
};
var ret = client.Search<Project>(s => s
.Query(q =>
active_date_from &&
active_date_to && q
.Match(d => d
.Query("free text")
)
)
.From(0)
.Size(10)
);
}
public class Project
{
public Availibility Availablity { get; set; }
public Contact Contact { get; set; }
}
public class Contact
{
public string Name { get; set; }
}
public class Availibility
{
public DateTime AvailableFrom { get; set; }
public DateTime AvailableTo { get; set; }
}
Your current query generates
POST http://localhost:9200/projects/project/_search?pretty=true
{
"from": 0,
"size": 10,
"query": {
"bool": {
"must": [
{
"range": {
"availablity.availableFrom": {
"lte": "2017-07-21T10:01:01.456794+10:00",
"time_zone": "+01:00",
"format": "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy",
"_name": "from",
"boost": 1.1
}
}
},
{
"range": {
"availablity.availableTo": {
"gt": "2017-07-21T10:01:01.456794+10:00",
"time_zone": "+01:00",
"format": "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy",
"_name": "toDate",
"boost": 1.1
}
}
}
]
}
}
}
If a nameField is added as the field for the match query you get
POST http://localhost:9200/projects/project/_search?pretty=true
{
"from": 0,
"size": 10,
"query": {
"bool": {
"must": [
{
"range": {
"availablity.availableFrom": {
"lte": "2017-07-21T10:02:23.896385+10:00",
"time_zone": "+01:00",
"format": "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy",
"_name": "from",
"boost": 1.1
}
}
},
{
"range": {
"availablity.availableTo": {
"gt": "2017-07-21T10:02:23.896385+10:00",
"time_zone": "+01:00",
"format": "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy",
"_name": "toDate",
"boost": 1.1
}
}
},
{
"match": {
"contact.name": {
"query": "free text"
}
}
}
]
}
}
}
Remove InMemoryConnection from ConnectionSettings if you actually want to execute the query against Elasticsearch and see the results.
The range query is a structured query where a document either matches or doesn't match the predicate. Because of this, it can be wrapped in a bool query filter clause which will forgo calculating a score for it and perform better. Because no scoring occurs, boost is not needed.
Putting this together
var availableToField = Infer.Field<Project>(f => f.Availablity.AvailableTo);
var availableFromField = Infer.Field<Project>(f => f.Availablity.AvailableFrom);
var nameField = Infer.Field<Project>(f => f.Contact.Name);
var active_date_to = new DateRangeQuery
{
Name = "toDate",
Field = availableToField,
GreaterThan = DateTime.Now,
TimeZone = "+01:00",
Format = "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy"
};
var active_date_from = new DateRangeQuery
{
Name = "from",
Field = availableFromField,
LessThanOrEqualTo = DateTime.Now,
TimeZone = "+01:00",
Format = "yyyy-MM-ddTHH:mm:SS||dd.MM.yyyy"
};
var ret = client.Search<Project>(s => s
.Query(q =>
+active_date_from &&
+active_date_to && q
.Match(d => d
.Field(nameField)
.Query("free text")
)
)
.From(0)
.Size(10)
);
You may also want to explore modelling available from and to as a date_range type
I do have a hard code json,I have to send that in http request using post,
This is the json
{
"RequestHeader": {
"UserName": " ",
"Password": " "
},
"RequestBody": {
"ChannelType": 1,
"BillAccountNumber": "1075-001",
"BillAccountType": null,
"PaymentAmount": 15.05,
"FeeAmount": 3.50,
"ABA": "111993776",
"BankAccount": "1234567899",
"EmailAddress": "jonah#doe.org",
"AccountHolder": "JonahDoe",
"WaiveFee": false,
"Recurring": false,
"CustomData": null
}
}
When i am passing this i am getting the right response
But when i am using the other it is not giving the response what i need, The only difference in first one my hard coded have \r\n and the 2nd one below don't have.
{
"RequestHeader": {
"UserName": " ",
"Password": " "
},
"RequestBody": {
"ChannelType": 1,
"BillAccountNumber": "1075-001",
"BillAccountType": null,
"PaymentAmount": 15.05,
"FeeAmount": 3.5,
"ABA": "111993776",
"BankAccount": "1234567899",
"EmailAddress": "jonah#doe.org",
"AccountHolder": "Jonah Doe",
"WaiveFee": false,
"Recurring": false,
"CustomData": null
}
}
Can some body tell me what is the problem.
Code IS:
class Program
{
static void Main(string[] args)
{
var RequestBody = new RequestBody
{
ChannelType = 1,
BillAccountNumber = "1075-001",
BillAccountType = null,
PaymentAmount = 15.05,
FeeAmount = 3.50,
ABA = "111993776",
BankAccount = "1234567899",
EmailAddress = "jonah#doe.org",
AccountHolder = "Jonah Doe",
WaiveFee = false,
Recurring = false,
CustomData = null
};
var RequestHeader = new RequestHeader
{
UserName = "myUname",
Password = "MyPass"
};
var Request = new Request
{
RequestBody = RequestBody,
RequestHeader = RequestHeader,
};
var ApiCredentials = new ApiCredentials
{
Request = Request
};
var httpWReq = (HttpWebRequest)WebRequest.Create("https://gw1.cwplab.com/api/Gateway/AuthorizeCheck");
httpWReq.ContentType = "application/json";
//httpWReq.Credentials = new NetworkCredential(" ", " ");
string data = "{\r\n\"RequestHeader\":{\r\n\"UserName\":\" \",\r\n\"Password\":\" \"\r\n},\r\n\"RequestBody\":{\r\n \"ChannelType\":1,\r\n \"BillAccountNumber\":\"1075-001\",\r\n \"BillAccountType\":null,\r\n \"PaymentAmount\":15.05,\r\n \"FeeAmount\":3.50,\r\n \"ABA\":\"111993776\",\r\n \"BankAccount\":\"1234567899\",\r\n \"EmailAddress\":\"jonah#doe.org\",\r\n \"AccountHolder\":\"Jonah Doe\",\r\n \"WaiveFee\":false,\r\n \"Recurring\":false,\r\n \"CustomData\":null\r\n}\r\n}\r\n";//Request.ToJSON();
string data1 = Newtonsoft.Json.JsonConvert.SerializeObject(Request);
httpWReq.ContentLength = data.Length;
httpWReq.Method = "POST";
using (StreamWriter stream = new StreamWriter(httpWReq.GetRequestStream()))
{
stream.Write(data);
//stream.Flush();
//stream.Close();
};
dynamic httpResponse = (HttpWebResponse)httpWReq.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
Console.WriteLine(result);
Console.ReadKey();
}
}
}
There is a difference in the JSON. I suspect your server doesn't accept the second json (you say you get the wrong response). \r\n are not mandatory, it is just for the reader.
"FeeAmount": 3.5,
"FeeAmount": 3.50,
And
"AccountHolder": "Jonah Doe",
"AccountHolder": "JonahDoe",
in NEST 2.x, I wrote code to query data like below:
var query = new QueryContainer();
query = query && new TermQuery { Field = "catId", Value = catId };
query = query && new NumericRangeQuery { Field ="price", GreaterThan = 10 };
var request =new SearchRequest<Project>
{
From = 0,
Size = 100,
Query = query,
Sort = new List<ISort>
{
new SortField { Field = "field", Order = SortOrder.Descending },
...
},
Type?? //problem comes here, how to specify type??
}
var response = _client.Search<Project>(request);
There are more than one type in my index, I want to query data in one of type.(just like query one of table data in a database), I hope in the SearchRequest object initializer have a "Type" parameter.
You can specify the indices and types in the constructor for SearchRequest<T>()
var catId = 1;
var query = new QueryContainer(new TermQuery { Field = "catId", Value = catId });
query = query && new NumericRangeQuery { Field = "price", GreaterThan = 10 };
var request = new SearchRequest<Project>("index-name", Types.Type(typeof(Project), typeof(AnotherProject)))
{
From = 0,
Size = 100,
Query = query,
Sort = new List<ISort>
{
new SortField { Field = "field", Order = Nest.SortOrder.Descending },
}
};
var response = client.Search<Project>(request);
would generate the following query
POST http://localhost:9200/index-name/project%2Canotherproject/_search?pretty=true
{
"from": 0,
"size": 100,
"sort": [
{
"field": {
"order": "desc"
}
}
],
"query": {
"bool": {
"must": [
{
"term": {
"catId": {
"value": 1
}
}
},
{
"range": {
"price": {
"gt": 10.0
}
}
}
]
}
}
}
I am able to create a flat serialized JSON string pretty easily with c#
My issue is I want to create a nested string like this below
[ {
title: "Yes",
id : "1",
menu: [ {
title: "Maybe",
id : "3",
alert : "No",
menu: [ {
title: "Maybe Not",
id : "8",
alert : "No",
menu: []
} ]
} ]
},
{
title: "No",
id : "2",
menu: []
}]
Any help would be great
Are you using MVC 3? - Do something like:
return Json(myObectWithListProperties, JsonRequestBehavior.AllowGet);
I use this to return complex C# objects that match the structure of the JavaScript objects I want.
e.g.:
var bob = new {
name = "test",
orders = new [] {
new { itemNo = 1, description = "desc" },
new { itemNo = 2, description = "desc2" }
}
};
return Json(bob, JsonRequestBehavior.AllowGet);
gives:
{
"name": "test",
"orders": [
{
"itemNo": 1,
"description": "desc"
},
{
"itemNo": 2,
"description": "desc2"
}
]
}
EDIT: A bit more nesting for fun:
var bob = new {
name = "test",
orders = new [] {
new { itemNo = 1, description = "desc" },
new { itemNo = 2, description = "desc2" }
},
test = new {
a = new {
b = new {
something = "testing",
someOtherThing = new {
aProperty = "1",
another = "2",
theThird = new {
bob = "quiteDeepNesting"
}
}
}
}
}
};
return Json(bob, JsonRequestBehavior.AllowGet);
gives:
{
"name": "test",
"orders": [
{
"itemNo": 1,
"description": "desc"
},
{
"itemNo": 2,
"description": "desc2"
}
],
"test": {
"a": {
"b": {
"something": "testing",
"someOtherThing": {
"aProperty": "1",
"another": "2",
"theThird": {
"bob": "quiteDeepNesting"
}
}
}
}
}
}
Try using
using System.Web.Script.Serialization;
//Assumed code to connect to a DB and get data out using a Reader goes here
Object data = new {
a = reader.GetString(field1),
b = reader.GetString(field2),
c = reader.GetString(field3)
};
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
string json = javaScriptSerializer.Serialize(data);
This is built-in and saves you the work of serializing to JSON yourself!
This example assumes you are getting data from a database using some sort of reader, and it then constructs the object you want to serialize using an anonymous class. Your anonymous class can be as simple or complex as you need it to be and the JavaScriptSerializer will handle transforming it to JSON. This approach is also useful because you can easily control the JSON property names it will create in the JSON.
using System.Web.Script.Serialization;
var strNJson = new
{
to = "hello",
notification = new
{
title = "textTitle",
body = "bodyText"
}
};
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
string json = javaScriptSerializer.Serialize(strNJson);
{ "to":"hello",
"notification": {
"title":"titleText",
"body":"bodyText"
}
}
You can make use of the ExpandoObject under the System.Dynamic namespace.
Here is a small snippet for achieving your solution:
dynamic parameters = new dynamic[2];
parameters[0] = new ExpandoObject();
parameters[0].title = "Yes";
parameters[0].id = "1";
parameters[0].menu = new dynamic[1];
parameters[0].menu[0] = new ExpandoObject();
parameters[0].menu[0].title = "Maybe";
parameters[0].menu[0].id = "3";
parameters[0].menu[0].alert = "No";
parameters[0].menu[0].menu = new dynamic[1];
parameters[0].menu[0].menu[0] = new ExpandoObject();
parameters[0].menu[0].menu[0].title = "Maybe Not";
parameters[0].menu[0].menu[0].id = "8";
parameters[0].menu[0].menu[0].alert = "No";
parameters[0].menu[0].menu[0].menu = new dynamic[0];
parameters[1] = new ExpandoObject();
parameters[1].title = "No";
parameters[1].id = "2";
parameters[1].menu = new dynamic[0];
string json = JsonConvert.SerializeObject(parameters, Formatting.Indented);
Console.WriteLine(json);
Here is the work in fiddle
Note: There are other ways to achieve this, but I have been using this approach.