.NET Core - Json.NET Deserialisation Mapping - asp.net-core

Is it possible to do mapping during the deserialization process of a JSON string to an object?
var resultObject = JsonConvert.DeserializeObject<ConfigItemGetResult>(result);
My JSON string is different from the object I want to deserialize to. So mapping has to happen. I'm trying to avoid making a model that maps 1 to 1 to the JSON string followed by mapping from object to object with for example AutoMapper.

Use Serialization Attributes for configuring your serialization mapping
public class JsonTest
{
[JsonProperty(PropertyName = "SomePropNameFromJson")]
public string SomeProp { get; set; }
[JsonProperty(PropertyName = "SomeNested")]
public SomeClass SomeClass { get; set; }
}
public class SomeClass
{
public SomeClass1 SomeClass1 { get; set; }
}
public class SomeClass1
{
public string text { get; set }
}
Here Json
{ "SomeProp":"value", "SomeNested":{
"SomeClass1":{
"text":"textvalue"
}
} }
Json convert trying to convert text to object by prop name with value via reflection if them finds prop name in text they take value if prop name has different name in JSON you can specify it via [JsonProperty(PropertyName = "SomeNested")] if this attr not set by default it will try get by prop name and it whatever what property is, it some object(your nested objects) or basic type, it will trying to convert it automaticaly.

Related

How to bind a collection with objects?

I need to bind a collection of objects from a querystring, but I cannot find the proper querystring format.
My controller code:
public class Filter
{
public string Name { get; set; }
public string Operator { get; set; }
public object Value { get; set; }
}
public void Get(IEnumerable<Filter> filters)
{
....
}
If you do want to pass the objects with querystring you could try as below:
https://localhost:44389/Test/Index?filters[0].Name=n1&filters[1].Name=n2&filters[2].Name=n3&filters[2].Value=v3
The result:
the offcial document related:
https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-6.0#collections
but i don't think it's a good solution,because the length of Url is limited,if your model has plenty properties and your collection has many elements ,you may get some error

C# type serialization not as a collection of key value pairs

I have a class that when serialized, I want to return as a single string without key value pairs. A string becomes a string. An int becomes an int. How do I make my class become a string?
Looking at DataContract and Serializable, it doesn't look that this is possible. The SerializationInfo.AddValue(name, value) setup forces your whole object into a key-value approach. I just want to return "A and B".
[DataContract]
public class MyObject
{
public int A { get; set; }
public int B { get; set; }
}
When serialized using the DataContractJsonSerializer, for example, I want it to be:
4 and 2
Not
{
"A": 4,
"B": 2
}
So let's say I have a parent class that uses both of these custom types:
[DataContract]
public class Parent
{
[DataMember]
public MyObject One { get; set; }
[DataMember]
public MyObject Two { get; set; }
}
I want to it serialize like this:
{
"One": "4 and 2",
"Two": "6 and 8"
}
Instead, the only thing I seem to be able to make it do is:
{
"One": {
"A": 4,
"B": 2
},
"Two": {
"A": 6,
"B": 8
}
}
The only solution that would work, is to add the custom serialization on Parent, setting One and Two accordingly, but I don't want to do that, I want my new class to get serialized as a string everywhere.
Can I serialize a type as a single return value? Or do all types besides built-in ones like int and string have to serialize to an object?
You can simply add a get attribute that returns the attributes as a string in any way that you like...
public class MyObject
{
public int A { get; set; }
public int B { get; set; }
public string MyNewStringAttribute {
get{
return A + " and " + B;
}
}
}
Then, when you can serialize from the controller using the new attribute from an array, linq, etc.
My answer: You can't.
The parent class, MyObject has to implement ISerializable to provide the custom serialization of the class itself. This places the responsibility of correctly serializing the class the way it is intended to each class that wishes to use it, which is an undesirable experience, and highlights a severe design flaw in the supported .NET custom serializer strategy.
[Serializable]
public class Parent : ISerializable
{
public MyObject One { get; set; }
public MyObject Two { get; set; }
public (SerializerInfo info, SerializerContext context)
{
string oneString = info.GetString("One");
One = new MyObject(oneString);
string twoString = info.GetString("Two");
Two = new MyObject(twoString);
}
public override void GetObjectData(SerializerInfo info, SerializerContext context)
{
info.AddValue("One", One.ToString());
info.AddValue("Two", Two.ToString());
}
}
Grumble grumble... add this to the long list of things that .NET has gotten wrong. Static / non interfaced classes for everything making the framework untestable by default without creating plug-n-chug wrappers for everything. Compilers with lossful MSIL/symbols. I could go on and on.

how can I deserialize map to different property name

my JSON string is like this.
string jsonstring1 = #"{'data':'N'}";
string jsonstring2 = #"{'data':[{'name':'jack','address':'la'}]}";
string jsonstring3 = #"{'data':{'flag':true}}";
how to define a class which can be used by those three JSON string deserialize to object?
Assuming that these three are your only possible JSON strings, you need to create three root classes. You can do this using some tools or simply by copying each of your JSON strings and pasting them by going to Edit > Paste Special > Paste JSON As Classes in Visual Studio. For instance the classes corresponding to jsonstring2 will look like this:
public class Rootobject
{
public Person[] data { get; set; }
}
public class Person
{
public string name { get; set; }
public string address { get; set; }
}
Then you need to detect the type of "data" like follows:
JObject jo = JObject.Parse(jsonstring2);
string type = jo["data"].GetType().Name;
which in this case will be JArray (the other two are JValue and JObject). Then you can deserialize the string to the correct class by using a switch statement.

Delegate the property display name translation to a handler

Current code in model:
[Display(Name = "E-mail")]
public string EMail { get; set; }
Desired code:
public string EMail { get; set; }
I would like to delegate the translation to a handler, something like this:
if(propertyName == "EMail") return "E-mail"
Based on my understanding of your question, I'm assuming that you are trying to implement localisation in your application.
If so, there are two options;
Resources
In .NET you can add Resource (.resx) files into your application to handle translation (one resx for each language). Then you can specify the Resource by specifying the ResourceType property of your Display attribute. For example;
public class Model
{
[Display(Name = "Email", ResourceType = typeof(Resources.Strings))]
public string Email { get; set; }
}
Custom attribute
Alternatively, if you are set on implementing this in a handler then you could implement a custom attribute, as demonstrated in this question.
Edit: Modified from the example in the above post.
If you add a new Resource file to your project - say Strings.resx and add "HelloWorld" as a field. You can then create a new attribute, such as LocalisedDisplayNameAttribute;
public class LocalisedDisplayNameAttribute : DisplayNameAttribute
{
public LocalisedDisplayNameAttribute(string resourceId)
: base(GetMessageFromResource(resourceId))
{
}
private static string GetMessageFromResource(string resourceId)
{
// "Strings" is the name of your resource file.
ResourceManager resourceManager = Strings.ResourceManager;
return resourceManager.GetString(resourceId);
}
}
You can then use it as follows;
public class Model
{
[LocalisedDisplayName("HelloWorld")]
public string Email { get; set; }
}
Let me know if I can help further,
Matt

Adding Prefix to property

I am creating Web API where i am in need to add prefix to property. Is it possible to prefix some text with a property in controller. For eg. I am having a class A
public class Stats
{
pubic bool IsStat { get; set; }
}
public HttpResponseMessage GetStats(Stats data)
{
}
The Web method GetStats is accessed by passing data as below
{Stat: true}
Now what I need to add Is prefix to the Stat property and so i will be getting true value for IsStat property in class Stats. Is it possible ?
You have 2 options:
Rename your IsStat property to Stat. This should then match the json data.
Use [DataContract] and [DataMember] attributes on your Stats class and use the IsStat property to tell the deserializer that IsStat should get it's data from the Stat property.
[DataContract]
public class Stats
{
[DataMember(Name = "Stat")]
public bool IsStat { get; set; }
}