When the cube is created and sum is chosen it returns a sum and a count in the value context when output as json. How can that be turned off so only the sum value is returned?
//define cube pivot
var cubeData = new PivotData(
new[] { "CloseDate", "StageName", "Type", "OpportunityName","Industry", "IsClosed", "IsWon" },
new SumAggregatorFactory("Amount"),
true);
json = new
{
cubeData,
};
return json;
Output shows
"cubeData": [
{
"key": [
"2019-07-05T00:00:00",
"Stage Value",
"Type Value",
"Opportunity Name Value",
"Industry Value",
false,
false
],
"value": {
"value": 35000.0,
"count": 1
}
},
PivotData has 2 serializable properties:
Count and Value.
If you want to prevent Value from being serialized, you would need to modify the PivotData class to [JsonIgnore] the Count property.
Alternatively, depending on your json implementation you can just remove the "count" element before returning.
json = new
{
cubeData,
};
json["value"].Value<JObject>().Remove("count");
return json;
Related
I have this result
{
"StatusCode": "200",
"Description": "Success",
"Data": [
{
"Language_Key": "btn_select_country",
"En_Val": "SELECT COUNTRY",
"Ar_Val": "اختر الدولة"
},
{
"Language_Key": "btn_continue",
"En_Val": "CONTINUE",
"Ar_Val": "استمرار"
}
]
}
I would like to achieve below result.
{
"StatusCode":"200",
"Description":"Success",
"Data":{
"btn_select_country":{
"En_Val":"SELECT COUNTRY",
"Ar_Val":"اختر الدولة"
},
"btn_continue":{
"En_Val":"CONTINUE",
"Ar_Val":"استمرار"
}
}
}
I want Language_Key to replace with column name and with 2 child nodes as EN and AR below is my code
Any hint is appreciated. Thanks
you serialize a dictionary where the key is your Language_Key:
Dictionary<string, Translation> dict = countryObj
.ToDictionary(o => o.Language_Key, o => new Translation { Ar_Val = o.Ar_Val, En_Val = o.En_Val});
rs.Data = dict;
json = new JavScriptSerializer().Serialize(rs);
You can use JsonProperty Attribute to rename properties after they get serialize.
https://www.newtonsoft.com/json/help/html/JsonPropertyName.htm
How to merge the object of the same key ignoring array wrapper([])?
Below example rows have properties named "elements[0]", "elements[1]" and "elements[2]".
The properties can be at any level on the JSON structure.
more than one array elements like elements[0],[1],[2],[3] and anotherelement[0],[1],[2],[3]
{
"addresses":[
"some address"
],
"rows":[
{
"elements[0]":{
"distance":{
"text":"227 mi",
"value":365468
},
"duration":{
"text":"3 hours 54 mins",
"value":14064
},
"status":"OK"
},
"elements[1]":{
"distance":{
"text":"94.6 mi",
"value":152193
},
"duration":{
"text":"1 hour 44 mins",
"value":6227
},
"status":"OK"
},
"elements[2]":{
"distance":{
"text":"2,878 mi",
"value":4632197
},
"duration":{
"text":"1 day 18 hours",
"value":151772
},
"status":"OK"
}
}
],
"status":[
"OK"
]
}
Expected is the element [{element0, element1, element2}].
{
"addresses":[
"some address"
],
"rows":[
{
"elements": [{
"distance": {
"text": "227 mi",
"value": 365468
},
"duration": {
"text": "3 hours 54 mins",
"value": 14064
},
"status": "OK"
},
{
"distance": {
"text": "94.6 mi",
"value": 152193
},
"duration": {
"text": "1 hour 44 mins",
"value": 6227
},
"status": "OK"
},
{
"distance": {
"text": "2,878 mi",
"value": 4632197
},
"duration": {
"text": "1 day 18 hours",
"value": 151772
},
"status": "OK"
}]}
],
"status":[
"OK"
]
}
The requirement is on the unknown JSON string so, can't create class/model. The above is just an example any generic code would be more helpful.
Updated ::
Thanks #dbc. It looks promising, the order elements will ascending for sure however other keys are swapped
{
"elements[0]": "Value 0",
"elements[1]": "Value 1",
"anotherelement[0]": "Another value 0",
"anotherelement[1]": "Another value 1",
"status" : "OK",
"lastitem" : "yes"
}
result is as below. Is there a way the order of the items as is. I know in JSON it won't affect but just to want to see if possible
{
"status" : "OK",
"lastitem" : "yes",
"elements": [
"Value 0",
"Value 1"
],
"anotherelement": [
"Another value 0",
"Another value 1"
]
}
expected is
{
"elements": [
"Value 0",
"Value 1"
],
"anotherelement": [
"Another value 0",
"Another value 1"
],
"status" : "OK",
"lastitem" : "yes"
}
To restate your problem, you have an arbitrary JSON hierarchy that contains properties whose names end in numerical indices in brackets, like the following (where the values could be of any type):
{
"elements[0]": "Value 0",
"elements[1]": "Value 1",
"anotherelement[0]": "Another value 0",
"anotherelement[1]": "Another value 1"
}
And you would like to transform them into array-valued properties by stripping off the bracketed indices and grouping and combining all the values with identical stripped property names, like so:
{
"elements": [
"Value 0",
"Value 1"
],
"anotherelement": [
"Another value 0",
"Another value 1"
]
}
This can be done using LINQ to JSON to edit your JSON hierarchy. You will also need to use a regular expression to pick out matching property names and a LINQ group statement to group together items with similar names.
The following extension method does the job:
public static partial class JsonExtensions
{
public static void FixElementArrays(this JToken root)
{
var regex = new Regex("^(.+)\\[[0-9]+\\]$");
if (root is JContainer container)
{
var query =
from o in container.DescendantsAndSelf().OfType<JObject>()
let matches = o.Properties()
.Select(p => (Property : p, Match : regex.Match(p.Name)))
.Where(m => m.Match.Success)
.Select(m => (m.Property, Name : m.Match.Groups[1].Value))
let groups = matches.GroupBy(m => m.Name)
from g in groups
select (Object : o, Name : g.Key, Values : g.Select(m => m.Property.Value).ToList());
foreach (var g in query.ToList())
{
IList<JToken> objAsList = g.Object;
// DescendantsAndSelf() returns items in document order, which ordering is preserved by GroupBy, so index of first item should be first index.
var insertIndex = objAsList.IndexOf(g.Values[0].Parent);
g.Values.ForEach(v => v.RemoveFromLowestPossibleParent());
objAsList.Insert(insertIndex, new JProperty(g.Name, new JArray(g.Values)));
}
}
}
public static JToken RemoveFromLowestPossibleParent(this JToken node)
{
if (node == null)
return null;
// If the parent is a JProperty, remove that instead of the token itself.
var property = node.Parent as JProperty;
var contained = property ?? node;
if (contained.Parent != null)
contained.Remove();
// Also detach the node from its immediate containing property -- Remove() does not do this even though it seems like it should
if (property != null)
property.Value = null;
return node;
}
}
Which you can use as follows:
var rootToken = JToken.Parse(jsonString);
rootToken.FixElementArrays();
var fixedJsonString = rootToken.ToString();
Notes:
You may need to tweak the regular expression based on your actual JSON property names. For instance, it's not clear from your question what to do with a name like "[0][1]".
The code assumes that the "elements[*]" properties are already in correct order, i.e. not
{
"elements[3]": "Value 3",
"elements[1]": "Value 1",
"elements[2]": "Value 2"
}
And as such puts them into the final array in the order they are encountered, rather than trying to order then by the index number inside the "elements[*]" property name.
Demo fiddle here.
Need to merge two json objects using c# based on spectific condition. If source JSON has "Enabled" property as "false" and destination JSON has same property as "true", then need to replace the value. Other wise no need to replace keep as same.
I tried like this :
o1.Merge(o2, new JsonMergeSettings
{
MergeArrayHandling = MergeArrayHandling.Merge
});
its overlapping the whole Object. Need to merge based on condition. Thanks in advance.
JSON 1:
{
"Name": "Sample",
"Array": [],
"Actions": [
{
"Name": "A",
"Enabled": false
},
{
"Name": "B",
"Enabled": true
}
]
}
JSON 2 :
{
"Name": "Sample",
"Array": [],
"Actions": [
{
"Name": "A",
"Enabled": true
},
{
"Name": "B",
"Enabled": false
}
]
}
I need Result JSON as below.
{
"Name": "Sample",
"Tabs": [],
"Actions": [
{
"Name": "A",
"Enabled": true
},
{
"Name": "B",
"Enabled": true
}
]
}
If source JSON has "Enabled" property as "false" and destination JSON has same property as "true", then need to replace the value. Other wise no need to replace keep as same.
One approach would be to,
Loop through Actions array in the destination json.
Read each object's Name and Enabled from the above array.
Retrieve the same object from source json.
Read its Name and Enabled.
Check whether property Name of both objects from json match and also check Enabled property of object from source json is false and Enabled property of object from destination json is true.
Rewrite the value of the property Enabled to true.
string json1 = "Your source json";
string json2 = "Your destination json";
JObject jObject1 = JObject.Parse(json1);
JObject jObject2 = JObject.Parse(json2);
//1
foreach (JObject obj2 in (JArray)jObject2["Actions"])
{
//2
var key2 = obj2["Name"].ToObject<string>();
var value2 = obj2["Enabled"].ToObject<bool>();
//3
var obj1 = jObject1["Actions"].Where(x => x["Name"].ToString() == key2).FirstOrDefault();
//4
var key1 = obj1["Name"].ToObject<string>();
var value1 = obj1["Enabled"].ToObject<bool>();
//5
if (key1 == key2 && value1 == false && value2 == true)
{
//6
obj2["Enabled"] = true;
}
}
string outputJson = jObject2.ToString();
I am using dynamic ExpandoObject() to create some json required for an NVD3/d3.js visualisation.
The nvd3 library is pretty explicit in what it needs with regards to data identifiers.
Exactly the json i need is the following -
[{
key: "AgeGroups",
values: [{
"label": "<20",
"value": 0
}, {
"label": ">20 <29",
"value": 160
}, {
"label": ">29 <39",
"value": 240
}]
}]
Note: the string 'key' must be lowercase and values must be pluralized.
With the following c#, I am able to get very close -
ageDemoJson.AgeGroups = new object[]
{
new { label = "<20", value = lessThan20 },
new { label = ">20 <29", value = between20and29 },
new { label = ">29 <39", value = between29and39 },
};
This outputs the following
[{
Key: "AgeGroups",
Value: [{
"label": "<20",
"value": 0
}, {
"label": ">20 <29",
"value": 160
}, {
"label": ">29 <39",
"value": 240
}]
}]
With this output, I need to customise the default behaviour of ExpandoObject and make the string 'Key' become 'key' and the string 'value' become 'values'
Is there anyway of doing this?
Of course I can work around this by parsing the json to string and replacing what I need in javascript, but would like if I didn't have to do that.
If you're using asp.net core you can change the JSON serialization by adding this line:
services.AddMvc()
.AddJsonOptions(opts =>
{
// Force Camel Case to JSON
opts.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
Or you can achive the same result by using Newtonsoft's Json.NET with this option:
string json = JsonConvert.SerializeObject(
yourObjectToSerialize,
new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }
);
I've spent MANY hours looking for the answer...
This is very easy in PHP but I just can't put it together in C#(I'm new to C# and mongo...)
I'm trying to iterate through all levels of a stored document. The document looks like this:
{
"_id": ObjectId("51f90101853bd88971ecdf27"),
"fields": [
{
"ID": ObjectId("51fd09498b080ee40c00514e"),
"NAME": "ID",
"TYPE": "Text"
},
{
"ID": ObjectId("51fd09a68b080ee40c0064db"),
"NAME": "Title",
"TYPE": "Text"
},
{
"ID": ObjectId("51fd09b28b080ee40c004d31"),
"NAME": "Start Date",
"TYPE": "Date"
},
{
"ID": ObjectId("51fd09c28b080ee40c007f2e"),
"NAME": "Long Description",
"TYPE": "Memo"
}
],
"name": "TODB",
"updated": "Wed Jul 31 2013 08:20:17 GMT-0400 (Eastern Daylight Time)"
}
I have no problem accessing the "name" and "updated" but can't figure out how to access the "fields" array.
Code so far :
{
MongoServer mongo = MongoServer.Create();
mongo.Connect();
var db = mongo.GetDatabase("forms");
mongo.RequestStart(db);
var collection = db.GetCollection("forms");
var query = new QueryDocument("name",
"TODB");
mongo.Disconnect();
}
#foreach(BsonDocument item in collection.Find(query))
{
#item.GetElement("name").Value
#item.GetElement("_id").Value
}
Again, I am able to access the name and _id just not any of the sub document values.
Thanks in advance for any assistance!
After I get the reading figured out, I am also going to want to write data....
There are a few ways, but here's one:
// build some test data
BsonArray dataFields = new BsonArray { new BsonDocument {
{ "ID" , ObjectId.GenerateNewId()}, { "NAME", "ID"}, {"TYPE", "Text"} } };
BsonDocument nested = new BsonDocument {
{ "name", "John Doe" },
{ "fields", dataFields },
{ "address", new BsonDocument {
{ "street", "123 Main St." },
{ "city", "Madison" },
{ "state", "WI" },
{ "zip", 53711}
}
}
};
// grab the address from the document,
// subdocs as a BsonDocument
var address = nested["address"].AsBsonDocument;
Console.WriteLine(address["city"].AsString);
// or, jump straight to the value ...
Console.WriteLine(nested["address"]["city"].AsString);
// loop through the fields array
var allFields = nested["fields"].AsBsonArray ;
foreach (var fields in allFields)
{
// grab a few of the fields:
Console.WriteLine("Name: {0}, Type: {1}",
fields["NAME"].AsString, fields["TYPE"].AsString);
}
You can often use the string indexer ["name-of-property"] to walk through the fields and sub document fields. Then, using the AsXYZ properties to cast the field value to a particular type as shown above.