I am trying to create the json from c# object which holds the data.
Data is in simple table format. Consist of Columns: Name, InputCode, DisplayID, CodeID, ParentID.
If Parent(Net) then ParentID is null. If Children(Subnet), has ParentID that holds CodeID of Parent(Net).
CodeID is Unique.
I am facing the issue with iternation under subnet using foreach. It dosen't allow.
public class CodeFrameJson
{
public string Name { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public int? InputCodeValue { get; set; }
public int DisplayId { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public List<CodeFrameJson> Subnet { get; set; }
}
List<CodeFrameJson> cfj = new List<CodeFrameJson>();
IEnumerable<CodeDTO> _cfd = new List<CodeDTO>();
_cfd = codeFrameJson.GetCodeFrame(questionId, projectName);
_cfd = _cfd.OrderBy(a => a.DisplayOrderNo).ToList();
foreach (var a in _cfd)
{
int CodesID = 0;
CodeFrameJson obj = new CodeFrameJson();
if (a.InputCodeValue == null)
{
var root = new CodeFrameJson()
{
Name = a.CodeName,
DisplayId = a.DisplayOrderNo,
InputCodeValue = null,
Subnet = new List<CodeFrameJson>()
{
//Start: Not allowing foreach
foreach (var x in _cfd)
{
if (x.ParentId == CodesID)
{
new CodeFrameJson()
{
Name = x.CodeName,
InputCodeValue = x.InputCodeValue,
DisplayId = x.DisplayOrderNo
};
}
}
//End: Not allowing foreach
}
};
obj = root;
}
else {
var root = new CodeFrameJson()
{
Name = a.CodeName,
DisplayId = a.DisplayOrderNo,
InputCodeValue = a.InputCodeValue,
Subnet = null
};
obj = root;
}
cfj.Add(obj);
}
var json = JsonConvert.SerializeObject(cfj, Formatting.Indented);
Final Output Something like this which can be distinguished easily
{
"Site": {
"Name": "Site",
"DisplayID": 1,
"Subnet": [
{
"Name": "Full Site",
"InputCodeValue": 1,
"DisplayId": 2
},
{
"Name": "Partial Site",
"InputCodeValue": 2,
"DisplayId": 3
}
]
},
"Test": {
"Name": "Test1",
"InputCodeValue": 3,
"DisplayId": 4
}
}
This doesn't really have to do anything with JSON, but with object (collection) initialization. You can only assign values there, but LinQ comes to the rescue:
Simply filter your list and create the new objects in the select statement:
Subnet = _cfd.Where(x => x.ParentId == CodesID).Select(x => new CodeFrameJson
{
Name = x.CodeName,
InputCodeValue = x.InputCodeValue,
DisplayId = x.DisplayOrderNo
}).ToList()
Related
I have a City_State list:
City_State[0].Range="\"city\":\"REDMOND\",\"state\":\"AK\"";
City_State[1].Range="\"city\":\"Alex City\",\"state\":\"
How to convert it into json like below:
var _pairs = new
{
criteria = new { cities = new[] { new { city = "REDMOND", state = "WA" },
new { city = "Alex City", state = "AL" } }
} ;
I tried the code below, but it does not work:
var _pairs = new { criteria = new { cities = new[] { _paged_City_State.ToArray() } } };
If you had these classes:
public class CityStateRaw
{
public string Range { get; set; }
}
public class CityState
{
public string City { get; set; }
public string State { get; set; }
}
The following code would work:
var ranges = new[]
{
new CityStateRaw { Range = "{\"city\":\"REDMOND\",\"state\":\"AK\"}" },
new CityStateRaw { Range = "{\"city\":\"Alex City\",\"state\":\"foo\"}" },
};
var list = ranges
.Select(raw => JsonConvert.DeserializeObject<CityState>(raw.Range))
.ToList();
But if this doesn't match your expectations you should be more concrete about what your exact input and the expected output should be.
Big apologies for the long post. I need to create the below json format for a post to rest api in c#. The below call works and I have used successfully in Postman to add it to the target system.
{
"item": {
"attrs": {
"attr": [{
"name": "IP_Category",
"value": "Miscellaneous"
}, {
"name": "Description",
"value": "Picture of Rabbit"
}, {
"name": "Title",
"value": "A Rabbit"
}
]
},
"resrs": {
"res": [{
"filename": "Rabbit.jpg",
"base64": "/9j/4AAQSkZJR"
}
]
},
"acl": {
"name": "Submitter"
},
"entityName": "IP_Document"
}
}
Based on the research I've done I need to copy and "paste special" into a new class file in visual studio so it can create the class objects based on the json format (Pretty cool!). And this is what it creates:
namespace BasicWebApp
{
public class Rootobject
{
public Item item { get; set; }
}
public class Item
{
public Attrs attrs { get; set; }
public Resrs resrs { get; set; }
public Acl acl { get; set; }
public string entityName { get; set; }
}
public class Attrs
{
public Attr[] attr { get; set; }
}
public class Attr
{
public string name { get; set; }
public string value { get; set; }
}
public class Resrs
{
public Re[] res { get; set; }
}
public class Re
{
public string filename { get; set; }
public string base64 { get; set; }
}
public class Acl
{
public string name { get; set; }
}
}
Problem 1: Why is vs renaming the res json object to to class Re? Is it a reserved word in c#?
Problem 2: I know I have to nest things in this fashion but I two levels deep and not sure what to code?
var model = new Rootobject();
model.item = new Item
{
attrs = new Attrs
{
attr = new List<Attr>
{
**now what??**
}
}
}
Don't have answer to your first question yet(but looking for it):
For your second question, at now what part you just do:
new Attr(){ name = "name1", value = "value1" },
new Attr(){ name = "name1", value = "value2" }
But that's not what i advise. I advise you to have your Attr collection ready then assign it. Like:
var model = new Rootobject();
model.item = new Item
{
attrs = yourAttrCollection
}
It also goes for everyting else you do. Have your stuff ready, then assign them. It increases readability in nested objects.
Problem 1: Why is vs renaming the res json object to to class Re? Is it a reserved word in c#?
No Re is not reserved word in class.
As mentioned by TheGeneral
res is plural for re's
You can use JsonProperty attribute to resolve this issue like
public class Resrs
{
[JsonProperty("res")]
public Re[] res { get; set; }
}
Problem 2: I know I have to nest things in this fashion but I two levels deep and not sure what to code?
var model = new Rootobject();
model.item = new Item
{
attrs = new Attrs
{
attr = new List<Attr>
{
new Attr { name = "abc", value = "ABC" },
new Attr { name = "pqr", value = "PQR" }
}
}
}
Thanks to all that responded. It helped. I ended up using the below code to create the json object I needed.
var model = new RootObject();
model.item = new Item
{
attrs = new Attrs
{
attr = new List<Attr>
{
new Attr { name = "IP_Category", value = ddlContent.Text },
new Attr { name = "Description", value = txtDesc.Text },
new Attr { name = "Title", value = txtTitle.Text }
}
},
resrs = new Resrs
{
res = new List<Re>
{
new Re { filename = fName, base64 = base64string},
}
},
acl = new Acl
{
name = "Submitter"
},
entityName = "IP_Document"
};
I am working on code which will give Cartesian product of two anonymous types. These 2 anonymous types are generated from database.
Code for 1st anonymous type:
private IEnumerable<object> GetItem()
{
return _unitOfWork.GetRepository<Item>()
.ListAll()
.Select(x => new
{
itemId = x.Id,
itemName = x.Name
})
}
Code for 2nd anonymous type:
private IEnumerable<object> GetVenue()
{
return _unitOfWork.GetRepository<Venue>()
.ListAll()
.Select(x => new
{
locationName = x.Address.City,
venueId = x.VenueId,
venueName = x.Name
})
}
I have following method to get the data and perform Cartesian product and return the data.
public object GetRestrictLookupInfo(IEnumerable<int> lookupCombinations)
{
IEnumerable<object> restrictList = new List<object>();
if (lookupCombinations.Contains(1))
{
var tempProductProfileList = GetItem();
restrictList = tempProductProfileList.AsEnumerable();
}
if (lookupCombinations.Contains(2))
{
var tempProductGroupList = GetVenue();
restrictList = (from a in restrictList.AsEnumerable()
from b in tempProductGroupList.AsEnumerable()
select new { a, b });
}
return restrictList;
}
I have controller which calls this method and return data in json format.
Controller Code
public HttpResponseMessage GetData(IEnumerable<int> lookupCombinations)
{
var lookupRestrictInfo = _sellerService.GetRestrictLookupInfo(lookupCombinations);
return Request.CreateResponse(HttpStatusCode.OK, lookupRestrictInfo);
}
Response expected is:-
[ {
"itemId": 1,
"itemName": "Music",
"locationName": "Paris",
"venueId": 99,
"venueName": "Royal Festival Hall"
} ]
Response which I receive is
[ {
"a": {
"itemId": 1,
"itemName": "Music"
},
"b": {
"locationName": "Paris",
"venueId": 99,
"venueName": "Royal Festival Hall" } }]
I am not able to get the expected JSON string.
You should start with the simplest possible code that shows your problem; your code above has a lot of complexities that may (or may not) have anything to do with your problem. Is this about manipulating anonymous types? Doing a Cartesian product with LINQ? Converting an object to JSON?
Here's one possible answer to what you might be looking for; notice that you can pass around anonymous types using generics instead of object.
namespace AnonymousTypes
{
class Program
{
static string Serialize(object o)
{
var d = (dynamic)o;
return d.ItemId.ToString() + d.ItemName + d.VenueId.ToString() + d.LocationName + d.VenueName;
}
static string GetData<T>(IEnumerable<T> result)
{
var retval = new StringBuilder();
foreach (var r in result)
retval.Append(Serialize(r));
return retval.ToString();
}
static string GetRestrictLookupInfo()
{
var restrictList = new[] { new { Id = 1, Name = "Music" }, new { Id = 2, Name = "TV" } };
var tempProductGroupList = new[] { new { LocationName = "Paris", Id = 99, Name = "Royal Festival Hall" } };
var result = from item in restrictList
from venue in tempProductGroupList
select new
{
ItemId = item.Id,
ItemName = item.Name,
LocationName = venue.LocationName,
VenueId = venue.Id,
VenueName = venue.Name
};
return GetData(result);
}
public static string GetData()
{
return GetRestrictLookupInfo();
}
static void Main(string[] args)
{
var result = GetData();
}
}
}
If that's not what you're looking for, you might start with code that doesn't use anonymous types, such as
namespace AnonymousTypes
{
sealed class Item
{
public int Id { get; set; }
public string Name { get; set; }
}
sealed class Venue
{
public string LocationName { get; set; }
public int Id { get; set; }
public string Name { get; set; }
}
sealed class ItemAndVenue
{
public int ItemId { get; set; }
public string ItemName { get; set; }
public string LocationName { get; set; }
public int VenueId { get; set; }
public string VenueName { get; set; }
}
class Program
{
static IEnumerable<Item> GetItem()
{
return new[] { new Item { Id = 1, Name = "Music" } };
}
static IEnumerable<Venue> GetVenue()
{
return new[] { new Venue { LocationName = "Paris", Id = 99, Name = "Royal Festival Hall" } };
}
static IEnumerable<ItemAndVenue> GetRestrictLookupInfo()
{
var restrictList = GetItem();
var tempProductGroupList = GetVenue();
var result = from item in restrictList
from venue in tempProductGroupList
select new ItemAndVenue
{
ItemId = item.Id,
ItemName = item.Name,
LocationName = venue.LocationName,
VenueId = venue.Id,
VenueName = venue.Name
};
return result;
}
static string GetData()
{
var v = GetRestrictLookupInfo().First();
return v.ItemId.ToString() + v.ItemName + v.VenueId.ToString() + v.LocationName + v.VenueName;
}
static void Main(string[] args)
{
var result = GetData();
}
}
}
In order to produce a single item in the output you need to create a new type, named or anonymous. Since you are using objects rather than actual types, the quickest approach is to cast them to dynamic:
var tempProductGroupList = GetVenue();
restrictList = (from a in restrictList.Cast<dynamic>()
from b in tempProductGroupList.Cast<dynamic>()
select new {
itemId = (int)a.itemId,
itemName = (string)a.itemName,
locationName = (string)b.locationName,
venueId = (int)b.venueId,
venueName = (string)b.venueName
});
This code is tightly coupled to the code producing both lists, because it assumes the knowledge of the field names of types passed into it dynamically. Any change in the structure of source data must be followed by a change in the code making combinations. In addition, it defeats run-time checking, so you need to be very careful with this code.
Try to create a simple object instead of nesting:
select new { a.itemId, a.itemName, b.locationName }
Like an option:
public object GetRestrictLookupInfo(IEnumerable<int> lookupCombinations)
{
List<Dictionary<string, object>> result = new List<Dictionary<string, object>>();
if (lookupCombinations.Contains(1))
{
var tmp = _unitOfWork.GetRepository<Item>()
.ListAll()
.Select(x => new
{
itemId = x.Id,
itemName = x.Name
})
.Select(x =>
{
var dic = new Dictionary<string, object>();
dic.Add(nameof(x.itemId), x.itemId);
dic.Add(nameof(x.itemName), x.itemName);
return dic;
});
result.AddRange(tmp);
}
if (lookupCombinations.Contains(2))
{
var tmp = _unitOfWork.GetRepository<Venue>()
.ListAll()
.Select(x => new
{
locationName = x.Address.City,
venueId = x.VenueId,
venueName = x.Name
})
.Select(x =>
{
var dic = new Dictionary<string, object>();
dic.Add(nameof(x.locationName), x.locationName);
dic.Add(nameof(x.venueId), x.venueId);
dic.Add(nameof(x.venueName), x.venueName);
return dic;
});
result = result.SelectMany(r => tmp.Select(t => r.Concat(t)));
}
return result;
}
It looks like some magic. I uses dictionary instead of object. It can be make in more clear way (extract few methods), but the idea should be clear.
Then, during serialization it will be presented as you need.
I need a final json format as follows and that should be dynamic.
{
"product_items" :
[
{
"_at" : 1,
"product_id" : "999"
},
{
"_at" : 2,
"quantity" : 2.00
},
{
"_delete_at" : 3
}
]
}
How to create a json format as above in the code._at field is dynamic.sometimes it might be 2 and sometimes it might be 10.I dont have idea on to generate the json dynamically in c#.
class Test
{
public ProductItem[] product_items { get; set; }
class ProductItem
{
public int[] _at { get; set; }
public int[] _delete { get; set; }
public int[] quantity { get; set; }
public string[] product_id{get;set;}
}
}
i have create the the properties for json as above.
I'm using Newtonsoft library
Your class should look more like this:
public class ProductItem
{
public int _at { get; set; }
public string product_id { get; set; }
public double? quantity { get; set; }
public int? _delete_at { get; set; }
}
public class ProductItemObject
{
public List<ProductItem> product_items { get; set; }
}
A example on serializing :
List<ProductItem> list = new List<ProductItem>();
ProductItemObject o = new ProductItemObject { product_items = list };
var item1 = new ProductItem { _at = 1, product_id = "001" };
var item2 = new ProductItem { _at = 2, quantity = 2.00 };
var item3 = new ProductItem { _delete_at = 3 };
list.Add(item1);
list.Add(item2);
list.Add(item3);
string json = JsonConvert.SerializeObject(o, Formatting.Indented);
// json string :
// {
// "product_items": [
// {
// "_at": 1,
// "product_id": "001",
// "quantity": null,
// "_delete_at": null
// },
// {
// "_at": 2,
// "product_id": null,
// "quantity": 2.0,
// "_delete_at": null
// },
// {
// "_at": 0,
// "product_id": null,
// "quantity": null,
// "_delete_at": 3
// }
// ]
//}
An alternative full dynamic that gets u the same Json string without any model :
var jsonObject = new JObject();
dynamic objectList = jsonObject;
objectList.product_items = new JArray() as dynamic;
dynamic item = new JObject();
item._at = 1;
item.product_id = "999";
objectList.product_items.Add(item);
item = new JObject();
item._at = 2;
item.quantity = 2.00;
objectList.product_items.Add(item);
item = new JObject();
item._delete_at = 3;
objectList.product_items.Add(item);
string json = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObject, Formatting.Indented);
Well, if I understand you properly and you just need to be able to generate that json, the product list should be dynamic with maybe anonymous classes then:
public class Products
{
public Products()
{
product_items = new List<dynamic>();
}
public List<dynamic> product_items { get; set; }
}
products.product_items.Add(new { _at = 1, product_id = "999" });
So I have some code that performs a Neo4j cypher query that returns an IEnumerable of type FolderObject like so:
public IEnumerable<FolderObject> GetChild(string parentId)
{
IEnumerable<FolderObject> childNode = null;
var query = GraphConnection.Cypher
.Start(new { n = Node.ByIndexLookup("node_auto_index", "ObjectId", parentId) })
.Match("(n)-[r:HAS_FOLDER]->(b)")
.Where("b.ParentId = n.ObjectId")
.Return<FolderObject>("b");
childNode = query.Results;
return childNode;
}
FolderObject looks like so:
public string ObjectId { get; set; }
public string ParentId {get; set;}
public List<GraphObject> Children { get; set; }
Then I have this method which works fine:
public List<FolderObject> GetChildren(string repositoryId, string folderId)
{
List<FolderObject> items;
QueryOperations query = new QueryOperations(GraphConnection);
var queryResult = query.GetChild(folderId);
string childId = null;
if (queryResult != null)
{
foreach (var item in queryResult)
{
childId = item.ObjectId;
items = new List<FolderObject>();
items.Add(item);
var nextChild = GetChildren(repositoryId, childId);
}
}
else
{
throw new Exception("The Folder with Id: " + folder + " could not be found.");
}
return items
}
Now the problem comes when I try and do this recursively. What I need to do is get the top most folder add that to a list then get the next folder below the top most and add that in as a child. Then repeat until there are no more children.
The structure as follows:
-Folder
-Folder
-Folder
-Folder
and return this structure as a List?
Here is the Json
{
"ParentId": "0",
"ObjectId": "1",
"children": [
{
"ParentId": "1",
"ObjectId": "2",
"children": [
{
"ParentId": "2",
"ObjectId": "3"
}
]
}
]
}
You could use a Stack<FolderObject> which is similar to a recursive method, the only difference is that it's not recursive. Imho it's more readable and less complex.
public List<FolderObject> GetChildren(string repositoryId, string folderId)
{
List<FolderObject> items = new List<FolderObject>();;
QueryOperations query = new QueryOperations(GraphConnection);
var queryResult = query.GetChild(folderId);
Stack<FolderObject> folders = new Stack<FolderObject>(queryResult);
while (folders.Count > 0)
{
FolderObject currentFolder = folders.Pop();
var childId = currentFolder.ObjectId;
items.Add(currentFolder);
var nextChildren = GetChildren(repositoryId, childId);
foreach (FolderObject child in nextChildren)
folders.Push(child);
}
return items;
}