I have this JSON array created in C#/aspx:
[
{
nome: "test",
apelido: "test"
}
]
And I want to create JSON like this:
{
success: 1,
error: 0,
gestor: "test",
cliente: [
{
nome: "test",
apelido: "test"
}
]
}
this is the code that i have:
var gestor = new JArray();
foreach (System.Data.DataRow item in com.Execute("select * from utilizadores").Rows)
{
gestor.Add(new JObject(new JProperty("nome", item["first_name"].ToString()),
new JProperty("apelido", item["last_name"].ToString())));
}
context.Response.Write(gestor);
I would just create a class for this (actually 2):
public class MyClass
{
public int success { get; set; }
public int error { get; set; }
public string gestor { get; set; }
public List<Cliente> cliente { get; set; }
}
public class Cliente
{
public string nome { get; set; }
public string apelido { get; set; }
}
And now you can loop to populate a list of these objects:
var myObj = new MyClass();
myObj.cliente = new List<Cliente>();
foreach (System.Data.DataRow item in com.Execute("select * from utilizadores").Rows)
{
myObj.cliente.Add(new Cliente()
{
nome = item["first_name"].ToString(),
apelido = item["last_name"].ToString()
};
}
// assuming that is successful
myObj.success = 1;
// not sure how you wanted this to be populated:
myObj.gestor = "test";
And now to serialize it you can just do:
context.Response.Write(JsonConvert.SerializeObject(myObj));
Charles' suggestion of anonymous classes is also perfectly fine if you have no other use for this class and it's not too complicated.
The most succinct way to do this is just with an anonymous class, if you are throwing this to some client side code and not really messing around with this exact object again elsewhere in server side code this is the easiest way to handle it.
var outputString = JsonConvert.SerializeObject(new {
success=1,
error=0,
gestor="test",
cliente = (from System.Data.DataRow i in com.Execute("select * from utilizadores").Rows
select new {
nome=item["first_name"],
apelido= item["last_name"]
}).ToArray()
});
Related
I want custom object in response of API having [required] data annotation on model properties like this:
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "fatal",
"code": "required",
"location": [
"/f:AllergyIntolerance/f:status"
]
}
]
}
Is it possible to do it or I would have to code it.
Because model validation happens before action is called, is there any way I can do it?
To create custom request and respond samples for your api, you can use Swashbuckle.AspNetCore.Swagger and to improve validations on your models you can use FluentValidations Sample. Good Luck!
first for simplify define your models like these :
public class ResponseModel
{
public string resourceType { get; set; }
public List<ResponseIssueModel> issue { get; set; } = new List<ResponseIssueModel>();
}
public class ResponseIssueModel
{
public string severity { get; set; }
public string code { get; set; }
public List<string> locations { get; set; } = new List<string>();
}
Then on your actions you can return this :
var response = new ResponseModel();
response.resourceType = "OperationOutcome";
response.issue.Add(new ResponseIssueModel
{
severity = "fatal",
code = "required",
locations = { "/f:AllergyIntolerance/f:status" }
});
return Ok(response);
you can use Builder Pattern for easy create response object
If you want to validate your model in controller,you could try with TryValidateModel method as mentioned in the document:
I tried as below:
in controller:
var model = new TestModel() { Id=1,nestedModels=new List<NestedModel>() { new NestedModel() { Prop1="P11"} } };
var isvalid=TryValidateModel(model);
var errorfiledlist = new List<string>();
if (!isvalid)
{
foreach (var value in ModelState.Values)
{
foreach (var error in value.Errors)
{
errorfiledlist.Add(MidStrEx(error.ErrorMessage,"The "," field"));
}
}
}
var jsonstring = JsonSerializer.Serialize(model);
foreach (var field in errorfiledlist)
{
var oldstr = String.Format("\"{0}\":null", field);
var newstr = String.Format("\"{0}\":\"required\"", field);
jsonstring = jsonstring.Replace(oldstr, newstr);
};
var obj = JsonSerializer.Deserialize<Object>(jsonstring);
return Ok(obj);
MidStrEx method:
public static string MidStrEx(string sourse, string startstr, string endstr)
{
string result = string.Empty;
int startindex, endindex;
try
{
startindex = sourse.IndexOf(startstr);
if (startindex == -1)
return result;
string tmpstr = sourse.Substring(startindex + startstr.Length);
endindex = tmpstr.IndexOf(endstr);
if (endindex == -1)
return result;
result = tmpstr.Remove(endindex);
}
catch (Exception ex)
{
}
return result;
}
Models:
public class TestModel
{
public int Id { get; set; }
[Required]
public string Prop { get; set; }
public List<NestedModel> nestedModels { get; set; }=new List<NestedModel>();
}
public class NestedModel
{
public string Prop1 { get; set; }
[Required]
public string Prop2 { get; set; }
}
The result:
I have a C# code that defines a constant JSON string and a corresponding POCO class. however i get an exception:
The JSON value could not be converted Path: $ | LineNumber: 0 | BytePositionInLine: 1.
Code
try
{
var filters = JsonSerializer.Deserialize <CmsContactsFilter>(FilterJson);
}
catch(Exception ex)
{
}
JSON
#"[{""cms"":""us-its"",""group"":[""ciso"",""cloudAdminsDistributionList"",""cloudAdmins""]},""cms"":""us-csdaudit"",""abc"":[""biso"",""costManagement""]},]";
POCO Class
public class CmsContactsFilter
{
public string Cms { get; set; }
public List<string> Group { get; set; }
}
Your json is not valid, here is the valid version of your json:
[
{
"cms": "us-its",
"group": [
"ciso",
"cloudAdminsDistributionList",
"cloudAdmins"
]
},
{
"cms": "us-csdaudit",
"group": [
"biso",
"costManagement"
]
}
]
Your code should be looks like this:
using System.Text.Json;
string filterJson = System.IO.File.ReadAllText("data.json");
var filters = JsonSerializer.Deserialize<List<CmsContactsFilter>>(filterJson);
foreach (var item in filters)
{
Console.WriteLine(item.cms+":");
foreach (var y in item.group)
{
Console.WriteLine("----"+y);
}
}
public class CmsContactsFilter
{
public string cms { get; set; }
public List<string> group { get; set; }
}
the name of the properties of the the CmsContactsFilter should be same with your json attributes names. if they are in lower-case format, your attribute name in the C# should be in the lower-case too.
your json is not valid, you need to add { to the second array item, and use an object collection for deserialization
var FilterJson = #"[{""cms"":""us-its"",""group"":[""ciso"",""cloudAdminsDistributionList"",""cloudAdmins""]},{""cms"":""us-csdaudit"",""abc"":[""biso"",""costManagement""]}]";
var filters = System.Text.Json.JsonSerializer.Deserialize <List<CmsContactsFilter>>(FilterJson);
and fix class
public class CmsContactsFilter
{
public string cms { get; set; }
public List<string> group { get; set; }
public List<string> abc { get; set; }
}
but as I understand your array has much more objects then 2. So you can try this code for the big json with different array names (if you had used Newtonsoft.Json this code could be significanly simplier)
JsonArray array = JsonNode.Parse(FilterJson).AsArray();
List<CmsContactsFilter> filters = new List<CmsContactsFilter>();
foreach (JsonObject item in array)
{
var obj = new CmsContactsFilter();
foreach (var prom in item.AsObject())
{
var name = prom.Key;
if (name == "cms")
{
obj.cms = prom.Value.ToString();
continue;
}
obj.groupName = name;
obj.group = System.Text.Json.JsonSerializer.Deserialize<List<string>>(prom.Value.ToString());
}
filters.Add(obj);
}
}
class
public class CmsContactsFilter
{
public string cms { get; set; }
public string groupName { get; set; }
public List<string> group { get; set; }
}
I am attempting to use the Newtonsoft JSON library to parse a JSON string dynamically using C#. In the JSON is a named array. I would like to remove the square brackets from this array and then write out the modified JSON.
The JSON now looks like the following. I would like to remove the square bracket from the ProductDescription array.
{
"Product": "123",
"to_Description": [
{
"ProductDescription": "Product 1"
}
]
}
Desired result
{
"Product": "123",
"to_Description":
{
"ProductDescription": "Product 1"
}
}
I believe I can use the code below to parse the JSON. I just need some help with making the modification.
JObject o1 = JObject.Parse(File.ReadAllText(#"output.json"));
The to_Description property starts off as List<Dictionary<string,string>> and you want to take the first element from the List.
So, given 2 classes
public class Source
{
public string Product {get;set;}
public List<Dictionary<string,string>> To_Description{get;set;}
}
public class Destination
{
public string Product {get;set;}
public Dictionary<string,string> To_Description{get;set;}
}
You could do it like this:
var src = JsonConvert.DeserializeObject<Source>(jsonString);
var dest = new Destination
{
Product = src.Product,
To_Description = src.To_Description[0]
};
var newJson = JsonConvert.SerializeObject(dest);
Note: You might want to check there really is just 1 item in the list!
Live example: https://dotnetfiddle.net/vxqumd
You do not need to create classes for this task. You can modify your object like this:
// Load the JSON from a file into a JObject
JObject o1 = JObject.Parse(File.ReadAllText(#"output.json"));
// Get the desired property whose value is to be replaced
var prop = o1.Property("to_Description");
// Replace the property value with the first child JObject of the existing value
prop.Value = prop.Value.Children<JObject>().FirstOrDefault();
// write the changed JSON back to the original file
File.WriteAllText(#"output.json", o1.ToString());
Fiddle: https://dotnetfiddle.net/M83zv3
I have used json2csharp to convert the actual and desired output to classes and manipulated the input json.. this will help in the maintenance in future
First defined the model
public class ToDescription
{
public string ProductDescription { get; set; }
}
public class ActualObject
{
public string Product { get; set; }
public List<ToDescription> to_Description { get; set; }
}
public class ChangedObject
{
public string Product { get; set; }
public ToDescription to_Description { get; set; }
}
Inject the logic
static void Main(string[] args)
{
string json = "{\"Product\": \"123\", \"to_Description\": [ { \"ProductDescription\": \"Product 1\" } ]} ";
ActualObject actualObject = JsonConvert.DeserializeObject<ActualObject>(json);
ChangedObject changedObject = new ChangedObject();
changedObject.Product = actualObject.Product;
changedObject.to_Description = actualObject.to_Description[0];
string formattedjson = JsonConvert.SerializeObject(changedObject);
Console.WriteLine(formattedjson);
}
Why not:
public class EntityDescription
{
public string ProductDescription { get; set; }
}
public class Entity
{
public string Product { get; set; }
}
public class Source : Entity
{
[JsonProperty("to_Description")]
public EntityDescription[] Description { get; set; }
}
public class Target : Entity
{
[JsonProperty("to_Description")]
public EntityDescription Description { get; set; }
}
var raw = File.ReadAllText(#"output.json");
var source = JsonConvert.DeserializeObject<Source>(raw);
var target = new Target { Product = source.Product, Description = source.Description.FirstOrDefault() };
var rawResult = JsonConvert.SerializeObject(target);
Update For dynamic JSON
var jObject = JObject.Parse(File.ReadAllText(#"output.json"));
var newjObject = new JObject();
foreach(var jToken in jObject) {
if(jToken.Value is JArray) {
List<JToken> l = jToken.Value.ToObject<List<JToken>>();
if(l != null && l.Count > 0) {
newjObject.Add(jToken.Key, l.First());
}
} else {
newjObject.Add(jToken.Key, jToken.Value);
}
}
var newTxt = newjObject.ToString();
From the following JSON data I want to put the station_code variables into a list. After this I want to use each station_code variable into a API URL call.
{
"request_time": "2015-02-19T08:33:39+00:00",
"stations": [
{
"station_code": "HWV",
"atcocode": null
},
{
"station_code": "HXX",
"atcocode": null
},
{
"station_code": "HAF",
"atcocode": null
}
]
}
This is the C# code I have attempting this
dynamic array = JsonConvert.DeserializeObject(json);
dynamic stations = array.stations;
var test = JObject.Parse(json);
var services = test.SelectTokens("stations[*].station_code").Select(t => (string)t).ToList();
JArray items = new JArray();
foreach (JObject station in stations)
{
items.Add(station["station_code"]);
}
int stationLength = 3;
for (int i = 0; i < stationLength; i++)
{
string localJson = get_local_departs("http://transportapi.com/v3/uk/train/station/"+ items[i] + "/live.json?app_id=03bf8009&app_key=d9307fd91b0247c607e098d5effedc97&train_status=passenger");
dynamic localStationArray = JsonConvert.DeserializeObject(localJson);
dynamic departures = localStationArray.departures;
dynamic localStationDeparts = departures.all;
foreach (var depart in localStationDeparts)
{
//info put into data tables
}
}
}
Well why can't you convert that to a strong type and use that instead like
public class stations
{
public string station_code { get; set; }
public string atcocode {get; set; }
}
public class Data
{
public DateTime request_time {get; set; }
public IEnumerable<stations> Stations {get; set; }
}
var result = JsonConvert.DeserializeObject<Data>(json);
foreach(stations s in result.Stations)
{
Console.WriteLine(s.station_code);
}
I have below scenario:
This is my class structure :
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public System.Collections.ObjectModel.Collection<Likes> Likes { get; set; }
}
public class Likes
{
public string Sport { get; set; }
public string Music { get; set; }
public string Food { get; set; }
public string Place { get; set; }
}
When I serialize object of User class then it will generate the below json string :
{"FirstName":"Naresh",
"LastName":"Parmar",
"Likes": [{"Sport":"Cricket",
"Music":"Classic",
"Food":"Gujarati",
"Place":"India"}]
}
I want to generate above json string like below:
{"FirstName":"Naresh",
"LastName":"Parmar",
"Sport":"Cricket",
"Music":"Classic",
"Food":"Gujarati",
"Place":"India"
}
I want the nested properties as primary one.
Any help would be appreciated.
Thanks in advance..
EDIT:
{"FirstName":"Naresh",
"LastName":"Parmar",
"Sport":"Cricket,Chess,Football",
"Music":"Classic",
"Food":"Gujarati",
"Place":"India"
}
It's really bad practice, since the code i'll post bellow doesn't have great maintainability, however if that's what you looking for, you can use this. Another class that have the format that you'd like, and have a method that adds a list of likes to the format you've required. That the class you should serialize to JSON:
class NestedUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Sport { get; set; }
public string Music { get; set; }
public string Food { get; set; }
public string Place { get; set; }
public void AddLikes(System.Collections.ObjectModel.Collection<Likes> likes)
{
foreach (Likes like in likes)
{
Sport += like.Sport + ",";
Music += like.Music + ",";
Food += like.Food + ",";
Place += like.Place + ",";
}
if (Sport != string.Empty)
{
Sport = Sport.Substring(0, Sport.Length - 1);
}
if (Music != string.Empty)
{
Music = Music.Substring(0, Music.Length - 1);
}
if (Food != string.Empty)
{
Food = Food.Substring(0, Food.Length - 1);
}
if (Place != string.Empty)
{
Place = Place.Substring(0, Place.Length - 1);
}
}
}
Since it's not only limited to Likes objects I'd suggest using dynamic objects. So the User class I propose is as follows:
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public dynamic Details { get; set; }
public User()
{
Details = new ExpandoObject();
}
public void AddSingleDetail(string key, string value)
{
var dict = this.Details as IDictionary<string, Object>;
if (dict.ContainsKey(key))
{
dict[key] += "," + value;
}
else
{
dict[key] = value;
}
}
public void AddDetails(object detailsObject)
{
var type = detailsObject.GetType();
foreach (var prop in type.GetProperties())
{
AddSingleDetail(prop.Name, prop.GetValue(detailsObject).ToString());
}
}
}
You can use it for adding single proerpties or adding an object as a whole. I used reflection to get all the property name and values and add them to the user details.
Sample usage:
static void Main(string[] args)
{
var user1 = new User() { FirstName = "Homer", LastName = "Simpson" };
user1.AddSingleDetail("Sport", "Bowling");
user1.AddSingleDetail("Sport", "Sleeping");
user1.AddSingleDetail("Food", "Donut");
user1.AddSingleDetail("Music", "Rock");
string flattenedHomer1 = ConvertUserToFlattenedJson(user1);
var user2 = new User() { FirstName = "Homer", LastName = "Simpson" };
var likes1 = new Likes() { Food = "Donut", Music = "Rock", Place = "Springfield", Sport = "Bowling" };
var likes2 = new Likes() { Food = "Steaks", Music = "Metal", Place = "Evergreen Terrace", Sport = "Sleeping" };
var proStuff = new ProfessionalStuff() { Title = "Boss" };
user2.AddDetails(likes1);
user2.AddDetails(likes2);
user2.AddDetails(proStuff);
string flattenedHomer2 = ConvertUserToFlattenedJson(user2);
}
And the method performing the JSON conversion is:
public static string ConvertUserToFlattenedJson(User u)
{
dynamic flatUser = new ExpandoObject();
flatUser.FirstName = u.FirstName;
flatUser.LastName = u.LastName;
var dict = u.Details as IDictionary<string, Object>;
foreach (var like in dict)
{
((IDictionary<string, Object>)flatUser)[like.Key] = like.Value;
}
string json = Newtonsoft.Json.JsonConvert.SerializeObject(flatUser);
return json;
}
In my sample above user2 is converted to the following JSON string which I believe is what you are looking for:
{
"FirstName": "Homer",
"LastName": "Simpson",
"Sport": "Bowling,Sleeping",
"Music": "Rock,Metal",
"Food": "Donut,Steaks",
"Place": "Springfield,Evergreen Terrace",
"Title": "Boss"
}
While concatenating strings you can check for null or duplicate values. I didn't handle that part.
For the sake of completeness, here's the ProfessionalStuff class I made up:
public class ProfessionalStuff
{
public string Title { get; set; }
}
Hope this helps.