My entities are like this:
class Address
{
public string Number { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string Country { get; set; }
}
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Address PostalAddress { get; set; }
}
Person newPerson =
new Person()
{
Name = "Kushan",
Age = 25,
PostalAddress =
new Address()
{
Number = "No 25",
Street = "Main Street",
City = "Matale",
Country = "Sri Lanka"
}
};
Now I wanna map this newPerson object into JSON object like this,
{
"PER_NAME" : "Kushan",
"PER_AGE" : "25",
"PER_ADDRESS" : {
"ADD_NUMBER" : "No 25",
"ADD_STREET" : "Main Street",
"ADD_CITY" : "Matale",
"ADD_COUNTRY" : "Sri Lanka"
}
}
Note: Above is just an example.
What I need is, I need to customize the Key at the serializing time. by default it is taking property name as the key. I can't change property names. How to do this?
Also, is it possible to change to order of appearing key-value pairs in JSON obj.?
You need to add DataContract attributes to your classes and DataMember to the properties. Set Name property of DataMemeber attribute to your custom property name and Order property to define the order.
[DataContract]
public class Person
{
[DataMember(Name = "PER_NAME", Order = 1)]
public string Name { get; set; }
[DataMember(Name = "PER_AGE", Order = 2)]
public int Age { get; set; }
[DataMember(Name = "PER_ADDRESS", Order = 3)]
public Address PostalAddress { get; set; }
}
Then you can do this:
var newPerson = new Person()
{
Name = "Kushan",
Age = 25,
PostalAddress = new Address()
{
Number = "No 25",
Street = "Main Street",
City = "Matale",
Country = "Sri Lanka"
}
};
MemoryStream stream = new MemoryStream();
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Person));
ser.WriteObject(stream, newPerson);
To check the result:
var result = Encoding.ASCII.GetString(stream.ToArray());
{"PER_NAME":"Kushan","PER_AGE":25,"PER_ADDRESS":{"ADD_NUMBER":"No 25","ADD_STREET":"Main Street","ADD_CITY":"Matale","ADD_COUNTRY":"Sri Lanka"}}
You can serialize an anonymous type with JavaScriptSerializer, so you might try projecting your object into the shape you want to serialize:
person.Select(s => new { PER_NAME = s.Name, PER_AGE = s.Age });
Related
I want to customize JavaScriptSerializer().Serialize by adding mapping.
Make it clear:
Think we have class:(as it comes from other library I can't modify this class, so I can not use [JsonProperty("")] )
class Address
{
public string Number { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string Country { get; set; }
}
output should be:
{
"NMB" : "No 25",
"STR" : "Main Street",
"CTY" : "Matale",
"CNT" : "Sri Lanka"
}
How can I achieve mapping during JavaScriptSerializer().Serialize(Address_Object);?
IMHO, the simpliest way would be to create an util to serialize, you can use a net serializer, or a Newtonsoft.Json one
var addr = new Address {....}
string json = SerializeAddress(addr);
public string SerializeAddress(Address address)
{
var addr = new
{
NMB = address.Number,
STR = address.Street,
CTY = address.City,
CNT = address.Country
};
return Newtonsoft.Json.JsonConvert.SerializeObject(addr, Newtonsoft.Json.Formatting.Indented);
//Or
return System.Text.Json.JsonSerializer.Serialize(addr);
}
I am trying to create a seed for my database in ASP.NET Core but I am having trouble with the relationships between the models. I have 3 models with 2 relationships. I have the following models:
public enum Grade
{
A, B, C, D, F
}
public class Enrollment
{
public Guid ID { get; set; } = Guid.NewGuid();
public Course Course { get; set; }
public Student Student { get; set; }
public Grade Grade { get; set; }
}
public class Course
{
public Guid ID { get; set; } = Guid.NewGuid();
public string Title { get; set; }
public int Credits { get; set; }
public List<Enrollment>? Enrollments { get; set; }
}
public class Student
{
public Guid ID { get; set; } = Guid.NewGuid();
public string LastName { get; set; }
public string FirstName { get; set; }
public DateTime EnrollmentDate { get; set; } = DateTime.Now;
public List<Enrollment>? Enrollments { get; set; }
}
On my DBContext I try to create the seed:
List<Student> students = new List<Student>()
{
new Student {FirstName = "Jaimie", LastName = "Vos", EnrollmentDate = DateTime.Now },
new Student {FirstName = "Bas", LastName = "Milius", EnrollmentDate = DateTime.Now },
new Student {FirstName = "Rien", LastName = "Bijl", EnrollmentDate = DateTime.Now },
new Student {FirstName = "Rajeck", LastName = "Massa", EnrollmentDate = DateTime.Now }
};
modelBuilder.Entity<Student>().HasData(students);
List<Course> courses = new List<Course>()
{
new Course {Title = "Wiskunde", Credits = 20},
new Course {Title = "Nederlands", Credits = 15},
new Course {Title = "Frans", Credits = 10},
};
modelBuilder.Entity<Course>().HasData(courses);
Enrollment test = new Enrollment();
test.Grade = Grade.A;
test.Course = courses[0];
test.Student = students[1];
modelBuilder.Entity<Enrollment>().HasData(test);
But when I run this I get the error:
The seed entity for entity type 'Enrollment' cannot be added because no value was provided for the required property 'CourseID'.
I followed the documentation for relations, does someone know a way to fix this issue?
I've found that you can just create a new object (not specifying the type) and give it a property specifying the related ID. So you should be able to do something like the following:
modelBuilder.Entity<Course>().HasData(new [] {
new { Title = "Frans", Credits = 10, Id = <courseGUID1> },
new { Title = "Nederlands", Credits = 15, Id = <courseGUID2> }
});
modelBuilder.Entity<Enrollment>().HasData(new [] {
new { Grade = Grade.A, CourseId = <courseGUID1>, StudentId = <studentGUID1> }
});
In conclusion, I hate seed data, but have used it a fair amount and the above solution seems to get me by. It's not intuitive and would be nice if the code you had worked!
I would assume that the IDs should be generated when created, but obviously that doesn't work.
PS: If using auto-incrementing integer IDs, I usually just use negative integers to avoid conflict with the generated IDs.
Let's suppose that I want to create the following document
{
"Id": "6a23a5f3-0f77-40a9-b9f9-26e88537a962",
"CarHistory": [
{ "model":"ford", "price": 100, "kilometers": 100 "current": true },
{ "model":"ford", "price": 200, "kilometers": 200, "current": false },
]
}
In Poco I guess that the model could look something among these lines:
public class Document
{
public Guid Id { get; set; }
}
public class Car : Document
{
public string Model {get; set;}
public decimal Price {get; set;}
public int Kilometers {get; set;}
public bool Current {get; set;}
}
So later I create..
public class MasterCar : Document
{
public ICollection<Car> CarHistory { get; set; } = new List<Car>();
}
All seems to work fine while debugging:
I create the Guid programmatically somewhere in a service like:
var masterCar = new MasterCar(){ Id = Guid.NewGuid() }
but when I go to the cosmos db emulator and a SELECT * FROM , and I checkout the Id property its value is:
"id": "00000000-0000-0000-0000-000000000000",
Can someone point me what Im doing wrong? or how this should be accomplished, I read that
you should not provide an Id yourself, BUT how can I access the Id property programmatically then?
For example:
CarService.GetById(Car.Id); //Id property doesnt exist if there is no property in poco
Below is my test code, you can have a try:
Document.cs
public class Document
{
[JsonProperty("id")]
public Guid Id { get; set; }
}
Car.cs
public class Car
{
[JsonProperty("model")]
public string Model { get; set; }
[JsonProperty("price")]
public decimal Price { get; set; }
[JsonProperty("kilometers")]
public int Kilometers { get; set; }
[JsonProperty("current")]
public bool Current { get; set; }
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
MasterCar.cs
public class MasterCar : Document
{
public ICollection<Car> CarHistory { get; set; } = new List<Car>();
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
create and search:
var guid = Guid.NewGuid();
var masterCar = new MasterCar() { Id = guid };
var car = new Car() { Model = "ford", Price = 100, Kilometers = 100, Current = true };
var car2 = new Car() { Model = "ford", Price = 200, Kilometers = 200, Current = false };
var carHistory = masterCar.CarHistory;
carHistory.Add(car);
carHistory.Add(car2);
CosmosClient client = new CosmosClient(connection_string);
Container container = client.GetContainer(databaseId, containerName);
await container.CreateItemAsync<MasterCar>(masterCar);
ItemResponse<MasterCar> itemResponse = await container.ReadItemAsync<MasterCar>(guid.ToString("D"), new PartitionKey(guid.ToString("D")));
Console.WriteLine(itemResponse.Resource.ToString());
Result:
I have an object Person like this:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Address { get; set; }
}
I tried to create a list like this:
var personList = new List<object>();
personList.Add(new Person { Address = "addr1", Age = 20, Name = "Person1" });
personList.Add(new Person { Address = "addr2", Age = 22, Name = "Person2" });
personList.Add(new Person { Address = "addr3", Age = 25, Name = "Person1" });
var jsonString = JsonConvert.SerializeObject(personList);
This is the result of jsonString
[{"Name":"Person1","Age":20,"Address":"addr1"},
{"Name":"Person2","Age":22,"Address":"addr2"},
{"Name":"Person1","Age":25,"Address":"addr3"}]
Below is my expected result, so how can I do that?
{
Person1:{"Name":"Person1","Age":20,"Address":"addr1"},
Person2:{"Name":"Person2","Age":22,"Address":"addr2"},
Person3:{"Name":"Person3","Age":25,"Address":"addr3"}
}
You have to use a Dictionary<string, Person> when I am not that wrong.
This should serialize it that way, you want it.
You can add the Attribute [JsonIgnore] to Name optionally, if you don't want redundant data.
Edit: You can serialize a list directly to a dictionary by using a custom JsonConverter: Newtonsoft.Json serialize collection (with indexer) as dictionary
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Address { get; set; }
// constructor
public Person(string name, int age, string address){
this.Name = name;
this.Age = age;
this.Address = address;
}
}
then
List<person>People = new List<person>();
People.Add(new Person("name1", 1, "address1"));
People.Add(new Person("name2", 2, "address2"));
People.Add(new Person("name3", 3, "address3"));
string jsonString = JsonConvert.SerializeObject(People);
then on the client, omitting the part about getting it to the client
var people = JSON.parse(jsonString)
Below is my class :
public class Employee : Base
{
public int Id { get; set; }
public string Fname { get; set; }
public DepartmentModel Department { get; set; }
}
public class DepartmentModel : Base
{
public int Id { get; set; }
public string DepartmentName { get; set; }
public List<Location> Locations { get; set; }
}
public class Locations
{
public string Area { get; set; }
public string StreetNo { get; set; }
public string Nearby { get; set; }
}
Response return from service:
var response = new
{
id = 100,
department = new
{
id = 200,
departmentName = "Abc",
locations = new[]
{
Employee.Department.Locations
.Select
(
lo => new
{
area = lo.Area,
streetNo = lo.streetNo,
nearby = lo.Nearby
}
).ToList()
}
}
};
return JsonConvert.SerializeObject(response);
Now when I try to deserialize this above JSON into my class Employee like below:
var deserialize = JsonConvert.DeserializeObject<Employee>(response.ToString());
Error:
How can I deserialize this above JSON?
The problem lies here:
locations = new[]
{
Employee.Department.Locations
.Select
(
lo => new
{
area = lo.Area,
streetNo = lo.streetNo,
nearby = lo.Nearby
}
).ToList()
}
The LINQ expression ends with .ToList() and thus is already returning a list of items. You are then wrapping that with new[] in an array. So, instead of being an array of Locations, the JSON is an array of an array of Locations.
Try removing the new[]. You don't want locations to be an array of lists
locations = Employee.Department.Locations
.Select(lo => new
{
area = lo.Area,
streetNo = lo.streetNo,
nearby = lo.Nearby
}
).ToList()
You need to instantiate a new Employee() and use the same casing as the classes:
var response = new Employee() // Instantiates Employee to ensure correct properties used.
{
Id = 100, // Has PascalCase.
Department = new DepartmentModel()
{
Id = 200,
DepartmentName = "Abc",
Locations = Employee.Department.Locations
.Select(lo => new Location
{
Area = lo.Area,
StreetNo = lo.StreetNo,
Nearby = lo.Nearby
}
).ToList()
}
};