This question already has answers here:
Use different name for serializing and deserializing with Json.Net
(3 answers)
Closed 5 years ago.
I am trying to read a JSON file, rename the property names, and export a new JSON with the new names. As stated in this example, https://www.newtonsoft.com/json/help/html/JsonPropertyName.htm, we can use JsonProperty to specify a different name internally in the code. However, when you export the json, it returns the original name. So in the example it still returned "release_date" instead of "ReleaseDate" when it was logged in the console. Is there any way to do this without creating a brand new object?
To clear things up, here is example of what I am trying to do:
JSON Input:
{ "name": "Starcraft", "release_date": "1998-01-01T00:00:00" }
Object Used to deserialize the data:
public class Videogame
{
public string name{ get; set; }
[JsonProperty("release_date")]
public DateTime releaseDate { get; set; }
}
Code that is called:
var json = JsonConvert.DeserializeObject<Videogame>(File.ReadAllText(path))
Console.WriteLine(JsonConvert.SerializeObject(json));
Resulted Output:
{ "name": "Starcraft", "release_date": "1998-01-01T00:00:00" }
Desired Output:
{ "name": "Starcraft", "releaseDate": "1998-01-01T00:00:00" }
The only way that I currently know how to solve it is to create a new object and use it to serialize my output. Wasn't sure if there is any simpler way to do this.
The following will work:
public class Videogame
{
public string name{ get; set; }
[JsonProperty("release_date")]
public DateTime old
{
set { ReleaseDate = value; }
}
[JsonProperty("releaseDate")]
public DateTime ReleaseDate { get; set; }
}
When deserializing, the old property will redirect its value to the new property.
Since the old property is a setter only, it will not be serialized back.
I would not consider this approach for large amounts of renaming. It's then better to follow the advices given in the comments.
You could use custom resolve to create desired behaviour:
public class CustomContractResolver : DefaultContractResolver
{
public bool UseJsonPropertyName { get; }
public CustomContractResolver(bool useJsonPropertyName)
{
UseJsonPropertyName = useJsonPropertyName;
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (!UseJsonPropertyName)
property.PropertyName = property.UnderlyingName;
return property;
}
}
public class ErrorDetails
{
public int Id { get; set; }
[JsonProperty("error_message")]
public string ErrorMessage { get; set; }
}
var json = "{'Id': 1,'error_message': 'An error has occurred!'}";
var serializerSettings = new JsonSerializerSettings()
{
ContractResolver = new CustomContractResolver(false)
};
var dezerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CustomContractResolver(true)
};
var obj = JsonConvert.DeserializeObject<ErrorDetails>(json, dezerializerSettings);
var jsonNew = JsonConvert.SerializeObject(obj, serializerSettings);
Kudos to NtFreX and his answer. I'm providing mine so that you can indicate that your question is resolved.
Related
I don't want to use Newtonsoft's Json.Net library. I'm avoiding any third-party dependencies if I can help it in this project.
If I have JSON that looks like this:
{
"has_more_items": false,
"items_html": "...",
"min_position": "1029839231781429248"
}
and I have a class that looks like this:
public class TwitterJson
{
bool hasMore { get; set; } // has_more_items
string rawText { get; set; } // items_html
string nextKey { get; set; } // min_position
}
and I have a JsonObject containing the above JSON:
JsonObject theJson = JsonObject.Parse(result);
How do I deserialize the JsonObject into my class? I've been trying to find a clear example of this, and everything I've found uses Json.Net.
I've been trying to find a clear example of this, and everything I've found uses Json.Net.
Because reinventing existing functionality is a waste of time especially when all the hard work has already been done for you.
If you insist on not using it then you will have to manually construct the object model based on the expected JSON.
For example, assuming publicly available properties
public class TwitterJson {
public bool hasMore { get; set; } // has_more_items
public string rawText { get; set; } // items_html
public string nextKey { get; set; } // min_position
}
Then parsing the above to the desired object model
JsonObject theJson = JsonObject.Parse(result);
var model = new TwitterJson {
hasMore = theJson.GetNamedBoolean("has_more_items"),
rawText = theJson.GetNamedString("items_html"),
nextKey = theJson.GetNamedString("min_position")
};
As mentioned by #Dimith, you need to decorate your class with [DataContract] and [DateMember], Please refer to below code which will convert your JSON into a given object.
// Deserialize a JSON string to a given object.
public static T ReadToObject<T>(string json) where T: class, new()
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
return ser.ReadObject(stream) as T;
}
}
Class:
[DataContract]
public class TwitterJson
{
[DataMember(Name = "has_more_items")]
bool hasMore { get; set; } // has_more_items
[DataMember(Name = "items_html")]
string rawText { get; set; } // items_html
[DataMember(Name = "min_position")]
string nextKey { get; set; } // min_position
}
Sample on how to use:
var result = "{\"has_more_items\": false, \"items_html\": \"...\",\"min_position\": \"1029839231781429248\"}";
var obj = ReadToObject<TwitterJson>(result);
You have to decorate your class with [DataContract] and [DataMember] attributes. Write the json into a memory stream and deserialize using DataContractJsonSerializer
Here is a more elaborated sample.
In addition to #Nkosi's answer below are some Comparisons between JSON.net and other alternatives:
JSON.Net vs DataContractJsonSerializer
JSON.Net vs Windows.Data.Json
I am serializing an object of this format using Newtonsoft.JSON:
class Message
{
public HeaderType Header { get; set; }
public object Body { get; set; }
}
I want to turn the Header and Body properties into camel case, while presevering the case of the properties of the thing assigned to Body.
So if the message looks like:
var result = new Message() { Header = myHeader, Body = new SomeClass() { A = 1 }});
I want the output to look like:
{ header = myHeader, body = { A = 1 } } // I realize this isn't valid C#
Right now, I'm doing this to get the camel case conversion, but of course it's affecting everything.
string stringRepresentationOfObj = JsonConvert.SerializeObject(obj, new JsonSerializerSettings {
ContractResolver = new DefaultContractResolver {
NamingStrategy = new CamelCaseNamingStrategy()
}
});
Is there a way to ignore certain parts of the object? I see that the docs call out OverrideSpecifiedNames, ProcessDictionaryKeys, and ProcessExtensionDataNames, but it doesn't look like that's what I want.
Am I forced to use a some kind of custom naming strategy? How can I achieve this?
You can configure a CamelCaseNamingStrategy to not camel case properties that already have a name specified with an attribute, Check documentation here
Specify property name as below
[JsonProperty(PropertyName = "Name")]
public string Name{ get; set; }
And in CamelCaseNamingStrategy set OverrideSpecifiedNames = false
string stringRepresentationOfObj = JsonConvert.SerializeObject(obj, new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new CamelCaseNamingStrategy()
{
OverrideSpecifiedNames = false
}
}
});
Another way is to modify your type only using JsonObject attribute as below,
this will force your type properties only to be in camelCase and any nested properties will not be affected.
[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
public class ApiMessage
{
public HeaderType Header { get; set; }
public object Body { get; set; }
}
Also, add JsonObject attribute to HeaderType class
[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
public class HeaderType
{
public string MyPropertyA { get; set; }
public string MyPropertyB { get; set; }
}
Your result should be as below
{
"header": {
"myPropertyA": "AAA",
"myPropertyB": "BBB"
},
"body": {
"ObjectPropertyA": "Value A",
"ObjectPropertyB": "Value B",
"ObjectPropertyC": "Value C"
}
}
You can create your own resolver to behave this way.
You'd create one, possibly have it look for a new attribute (which you'd create), that you can then use to decorate the properties you don't want camelCased.
I am receiving JSON data from a web API that looks like this:
[
{
"id": 1
"error_message": "An error has occurred!"
}
]
I deserialize this data to objects of the following type:
public class ErrorDetails
{
public int Id { get; set; }
[JsonProperty("error_message")]
public string ErrorMessage { get; set; }
}
Later in my application I would like to serialize the ErrorDetails object again to JSON but using the property name ErrorMessage instead of error_message. So the result would look like this:
[
{
"Id": 1
"ErrorMessage": "An error has occurred!"
}
]
Is there an easy way I can accomplish this with Json.Net? Perhaps using a custom resolver and some attributes like:
public class ErrorDetails
{
public int Id { get; set; }
[SerializeAs("ErrorMessage")]
[DeserializeAs("error_message")]
public string ErrorMessage { get; set; }
}
But the resolver doesn't tell me when I'm serializing or deserializing.
You can make use of the JsonSerializerSettings, the ContractResolver and the NamingStrategy.
public class ErrorDetails
{
public int Id { get; set; }
public string ErrorMessage { get; set; }
}
var json = "{'Id': 1,'error_message': 'An error has occurred!'}";
For dezerialization you could use the SnakeCaseNamingStrategy.
var dezerializerSettings = new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
}
};
var obj = JsonConvert.DeserializeObject<ErrorDetails>(json, dezerializerSettings);
To serialize the object again you dont have to change the JsonSerializerSettings as the default will use the property name.
var jsonNew = JsonConvert.SerializeObject(obj);
jsonNew = "{'Id': 1,'ErrorMessage': 'An error has occurred!'}"
Or you could create a contract resolver which can decide which name to use. Then you can decide when you dezerialize and serialize if you want to use the pascal case name format or the one with the underscore.
public class CustomContractResolver : DefaultContractResolver
{
public bool UseJsonPropertyName { get; }
public CustomContractResolver(bool useJsonPropertyName)
{
UseJsonPropertyName = useJsonPropertyName;
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (!UseJsonPropertyName)
property.PropertyName = property.UnderlyingName;
return property;
}
}
public class ErrorDetails
{
public int Id { get; set; }
[JsonProperty("error_message")]
public string ErrorMessage { get; set; }
}
var json = "{'Id': 1,'error_message': 'An error has occurred!'}";
var serializerSettings = new JsonSerializerSettings()
{
ContractResolver = new CustomContractResolver(false)
};
var dezerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CustomContractResolver(true)
};
var obj = JsonConvert.DeserializeObject<ErrorDetails>(json, dezerializerSettings);
var jsonNew = JsonConvert.SerializeObject(obj, serializerSettings);
jsonNew = "{'Id': 1,'ErrorMessage': 'An error has occurred!'}"
Another way of achieving a different property name when serialising vs deserisalising is by using the ShouldSerialize method: https://www.newtonsoft.com/json/help/html/ConditionalProperties.htm#ShouldSerialize
The docs say:
To conditionally serialize a property, add a method that returns
boolean with the same name as the property and then prefix the method
name with ShouldSerialize. The result of the method determines whether
the property is serialized. If the method returns true then the
property will be serialized, if it returns false then the property
will be skipped.
E.g:
public class ErrorDetails
{
public int Id { get; set; }
// This will deserialise the `error_message` property from the incoming json into the `GetErrorMessage` property
[JsonProperty("error_message")]
public string GetErrorMessage { get; set; }
// If this method returns false then the property after the `ShouldSerialize` prefix will not be serialised into the output
public bool ShouldSerializeGetErrorMessage() => false;
// The serialised output will return `ErrorMessage` with the value from `GetErrorMessage` i.e. `error_message` in the original json
public string ErrorMessage { get { return GetErrorMessage; } }
}
This results in slightly more overhead so be careful if dealing with lots of properties or with lots of data but for small payloads, and if you don't mind messing up your DTO class a little, then this could be a quicker solution than writing custom contract resolvers etc.
I liked the answer by #lee_mcmullen, and implemented it in my own code. Now I think I've found a slightly neater version.
public class ErrorDetails
{
public int Id { get; set; }
// This will deserialise the `error_message` property from the incoming json and store it in the new `GetErrorMessage` property
[JsonProperty("error_message")]
public string GetErrorMessage { get { return ErrorMessage; } set { ErrorMessage = value; } }
// If this method returns false then the property after the `ShouldSerialize` prefix will not be serialised into the output
public bool ShouldSerializeGetErrorMessage() => false;
// The serialised output will return `ErrorMessage` with the value set from `GetErrorMessage` i.e. `error_message` in the original json
public string ErrorMessage { get; set; }
}
The reason I like this better is that in more complicated models it allows for inheritance while keeping all of the "old" custom stuff separate
public class ErrorDetails
{
public int Id { get; set; }
public string ErrorMessage { get; set; }
}
// This is our old ErrorDetails that hopefully we can delete one day
public class OldErrorDetails : ErrorDetails
{
// This will deserialise the `error_message` property from the incoming json and store it in the new `GetErrorMessage` property
[JsonProperty("error_message")]
public string GetErrorMessage { get { return ErrorMessage; } set { ErrorMessage = value; } }
// If this method returns false then the property after the `ShouldSerialize` prefix will not be serialised into the output
public bool ShouldSerializeGetErrorMessage() => false;
}
I'm communicating with a JSON-based API which I can't change. It always returns a Response object with a varying Result object inside. Typically it looks like this:
{ "ver": "2.0", "result": { "code": 0 } }
For certain commands the Result object is 'grown' by adding extra properties:
{ "ver": "2.0", "result": { "code": 0, "hostName": "sample", "hostPort": 5000 } }
I've used Newtonsoft attributes to define the objects as follows:
internal class RpcResponse
{
[JsonProperty(PropertyName = "ver")]
public string Version { get; set; }
[JsonProperty(PropertyName = "result")]
public RpcResponseResult Result
{
get;
set;
}
internal class RpcResponseResult
{
[JsonProperty(PropertyName = "code")]
public int Code { get; set; }
}
internal class RpcExtendedResponseResult: RpcResponseResult
{
[JsonProperty(PropertyName = "hostName")]
public string HostName { get; set; }
[JsonProperty(PropertyName = "hostPort")]
public int HostPort { get; set; }
But when the Response object is deserialized:
RpcResponse rspResponse = JsonConvert.DeserializeObject<RpcResponse>(rspString);
Its Result property always appears as an RpcResponseResult object, ie. JsonConvert doesn't know to construct it as a RpcExtendedResponseResult object.
Is there some way with Attributes or Converters to reinstate the correct descendent object? I feel like I'm missing something obvious!
It's because the type of the object is RpcResponseResult. The deserializer can only deserialize fields that are declared in the type of the field specified. It can't determine because a class has "hostName" its now an RpcExtendedResponseResult.
If I were doing this, I might make the result a container for all possible fields with default values if needed, and then you can fill another object as needed.
internal class RpcResponseResultContainer
{
[JsonProperty(PropertyName = "code")]
public int Code { get; set; }
[JsonProperty(PropertyName = "hostName")]
private string mHostName = string.Empty;
public string HostName
{
get { return mHostName;}
set { mHostName = value; }
}
[JsonProperty(PropertyName = "hostPort")]
private int mHostPort = -1;
public int HostPort
{
get { return mHostPort;}
set { mHostPort = value;}
}
Then if you really wanted to get your object as you want it, you could do something like this in your container class:
public RpcResponseResult GetActualResponseType()
{
if(HostPort != -1 && !string.IsNullOrEmtpy(HostName))
{
return new RpcExtendedResponseResult() { Code = this.Code, HostName = this.HostName, HostPort = this.HostPort};
}
return new RpcResponseResult() { Code = this.Code };
}
First, credit to Matthew Frontino for providing the only answer which I've accepted.
However I opted not to make a single result container, so here's what I ended up doing.
First I started with this page: How to implement custom JsonConverter in JSON.NET to deserialize a List of base class objects?
I used the version of JsonCreationConverter provided there by Alain.
I added the CanWrite override as suggested there by Dribbel:
public override bool CanWrite
{
get { return false; }
}
I also added my own helper function to JsonCreationConverter:
protected bool FieldExists(string fieldName, JObject jObject) {
return jObject[fieldName] != null;
}
Then I created my own converter as follows:
class RpcResponseResultConverter : JsonCreationConverter<RpcResponseResult>
{
protected override RpcResponseResult Create(Type objectType, JObject jObject)
{
// determine extended responses
if (FieldExists("hostName", jObject) &&
FieldExists("hostPort", jObject) )
{
return new RpcExtendedResponseResult();
}
//default
return new RpcResponseResult();
}
}
Then I deserialize the top-level class and supply any converters to be used. In this case I only supplied one, which was for the nested class in question:
RpcResponse rspResponse = JsonConvert.DeserializeObject<RpcResponse>(
rspString,
new JsonSerializerSettings {
DateParseHandling = Newtonsoft.Json.DateParseHandling.None,
Converters = new List<JsonConverter>( new JsonConverter[] {
new RpcResponseResultConverter()
})
});
Notes:
Anything not explicitly handled by a converter (such as the top-level class) is deserialized using the default converter built into JsonConvert.
This only works if you can identify a unique set of fields for every descendent class.
I'm using an MVC 4 web API and asp.net web forms 4.0 to build a rest API. It's working great:
[HttpGet]
public HttpResponseMessage Me(string hash)
{
HttpResponseMessage httpResponseMessage;
List<Something> somethings = ...
httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK,
new { result = true, somethings = somethings });
return httpResponseMessage;
}
Now I need to prevent some properties to be serialized. I know I can use some LINQ over the list and get only the properties I need, and generally it's a good approach, but in the present scenario the something object is too complex, and I need a different set of properties in different methods, so it's easier to mark, at runtime, each property to be ignored.
Is there a way to do that?
ASP.NET Web API uses Json.Net as default formatter, so if your application just only uses JSON as data format, you can use [JsonIgnore] to ignore property for serialization:
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
[JsonIgnore]
public List<Something> Somethings { get; set; }
}
But, this way does not support XML format. So, in case your application has to support XML format more (or only support XML), instead of using Json.Net, you should use [DataContract] which supports both JSON and XML:
[DataContract]
public class Foo
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
//Ignore by default
public List<Something> Somethings { get; set; }
}
For more understanding, you can read the official article.
According to the Web API documentation page JSON and XML Serialization in ASP.NET Web API to explicitly prevent serialization on a property you can either use [JsonIgnore] for the Json serializer or [IgnoreDataMember] for the default XML serializer.
However in testing I have noticed that [IgnoreDataMember] prevents serialization for both XML and Json requests, so I would recommend using that rather than decorating a property with multiple attributes.
Instead of letting everything get serialized by default, you can take the "opt-in" approach. In this scenario, only the properties you specify are allowed to be serialized. You do this with the DataContractAttribute and DataMemberAttribute, found in the System.Runtime.Serialization namespace.
The DataContactAttribute is applied to the class, and the DataMemberAttribute is applied to each member you want to be serialized:
[DataContract]
public class MyClass {
[DataMember]
public int Id { get; set;} // Serialized
[DataMember]
public string Name { get; set; } // Serialized
public string DontExposeMe { get; set; } // Will not be serialized
}
Dare I say this is a better approach because it forces you to make explicit decisions about what will or will not make it through serialization. It also allows your model classes to live in a project by themselves, without taking a dependency on JSON.net just because somewhere else you happen to be serializing them with JSON.net.
This worked for me: Create a custom contract resolver which has a public property called AllowList of string array type. In your action, modify that property depending on what the action needs to return.
1. create a custom contract resolver:
public class PublicDomainJsonContractResolverOptIn : DefaultContractResolver
{
public string[] AllowList { get; set; }
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
properties = properties.Where(p => AllowList.Contains(p.PropertyName)).ToList();
return properties;
}
}
2. use custom contract resolver in action
[HttpGet]
public BinaryImage Single(int key)
{
//limit properties that are sent on wire for this request specifically
var contractResolver = Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver as PublicDomainJsonContractResolverOptIn;
if (contractResolver != null)
contractResolver.AllowList = new string[] { "Id", "Bytes", "MimeType", "Width", "Height" };
BinaryImage image = new BinaryImage { Id = 1 };
//etc. etc.
return image;
}
This approach allowed me to allow/disallow for specific request instead of modifying the class definition. And if you don't need XML serialization, don't forget to turn it off in your App_Start\WebApiConfig.cs or your API will return blocked properties if the client requests xml instead of json.
//remove xml serialization
var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
I will show you 2 ways to accomplish what you want:
First way: Decorate your field with JsonProperty attribute in order to skip the serialization of that field if it is null.
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public List<Something> Somethings { get; set; }
}
Second way: If you are negotiation with some complex scenarios then you could use the Web Api convention ("ShouldSerialize") in order to skip serialization of that field depending of some specific logic.
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
public List<Something> Somethings { get; set; }
public bool ShouldSerializeSomethings() {
var resultOfSomeLogic = false;
return resultOfSomeLogic;
}
}
WebApi uses JSON.Net and it use reflection to serialization so when it has detected (for instance) the ShouldSerializeFieldX() method the field with name FieldX will not be serialized.
I'm late to the game, but an anonymous objects would do the trick:
[HttpGet]
public HttpResponseMessage Me(string hash)
{
HttpResponseMessage httpResponseMessage;
List<Something> somethings = ...
var returnObjects = somethings.Select(x => new {
Id = x.Id,
OtherField = x.OtherField
});
httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK,
new { result = true, somethings = returnObjects });
return httpResponseMessage;
}
Try using IgnoreDataMember property
public class Foo
{
[IgnoreDataMember]
public int Id { get; set; }
public string Name { get; set; }
}
Works fine by just adding the:
[IgnoreDataMember]
On top of the propertyp, like:
public class UserSettingsModel
{
public string UserName { get; set; }
[IgnoreDataMember]
public DateTime Created { get; set; }
}
This works with ApiController. The code:
[Route("api/Context/UserSettings")]
[HttpGet, HttpPost]
public UserSettingsModel UserSettings()
{
return _contextService.GetUserSettings();
}
Almost same as greatbear302's answer, but i create ContractResolver per request.
1) Create a custom ContractResolver
public class MyJsonContractResolver : DefaultContractResolver
{
public List<Tuple<string, string>> ExcludeProperties { get; set; }
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (ExcludeProperties?.FirstOrDefault(
s => s.Item2 == member.Name && s.Item1 == member.DeclaringType.Name) != null)
{
property.ShouldSerialize = instance => { return false; };
}
return property;
}
}
2) Use custom contract resolver in action
public async Task<IActionResult> Sites()
{
var items = await db.Sites.GetManyAsync();
return Json(items.ToList(), new JsonSerializerSettings
{
ContractResolver = new MyJsonContractResolver()
{
ExcludeProperties = new List<Tuple<string, string>>
{
Tuple.Create("Site", "Name"),
Tuple.Create("<TypeName>", "<MemberName>"),
}
}
});
}
Edit:
It didn't work as expected(isolate resolver per request). I'll use anonymous objects.
public async Task<IActionResult> Sites()
{
var items = await db.Sites.GetManyAsync();
return Json(items.Select(s => new
{
s.ID,
s.DisplayName,
s.Url,
UrlAlias = s.Url,
NestedItems = s.NestedItems.Select(ni => new
{
ni.Name,
ni.OrdeIndex,
ni.Enabled,
}),
}));
}
You might be able to use AutoMapper and use the .Ignore() mapping and then send the mapped object
CreateMap<Foo, Foo>().ForMember(x => x.Bar, opt => opt.Ignore());
For .NET Core 3.0 and above:
The default JSON serializer for ASP.NET Core is now System.Text.Json, which is new in .NET Core 3.0. Consider using System.Text.Json when possible. It's high-performance and doesn't require an additional library dependency.
https://learn.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.1&tabs=visual-studio#newtonsoftjson-jsonnet-support
Sample (Thanks cuongle)
using System.Text.Json.Serialization;
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
[JsonIgnore]
public List<Something> Somethings { get; set; }
}
If you already have Newtonsoft.Json intalled and chose to use it instead, by default, [JsonIgnore] won't work as expected.
For some reason [IgnoreDataMember] does not always work for me, and I sometimes get StackOverflowException (or similar). So instead (or in addition) i've started using a pattern looking something like this when POSTing in Objects to my API:
[Route("api/myroute")]
[AcceptVerbs("POST")]
public IHttpActionResult PostMyObject(JObject myObject)
{
MyObject myObjectConverted = myObject.ToObject<MyObject>();
//Do some stuff with the object
return Ok(myObjectConverted);
}
So basically i pass in an JObject and convert it after it has been recieved to aviod problems caused by the built-in serializer that sometimes cause an infinite loop while parsing the objects.
If someone know a reason that this is in any way a bad idea, please let me know.
It may be worth noting that it is the following code for an EntityFramework Class-property that causes the problem (If two classes refer to each-other):
[Serializable]
public partial class MyObject
{
[IgnoreDataMember]
public MyOtherObject MyOtherObject => MyOtherObject.GetById(MyOtherObjectId);
}
[Serializable]
public partial class MyOtherObject
{
[IgnoreDataMember]
public List<MyObject> MyObjects => MyObject.GetByMyOtherObjectId(Id);
}