-2

I have an API that returns some data of a class in JSON. Is there any way to return only some specific fields of a C# class in JSON?

For example:

class Person {
    public int Id{ get; set; }
    public string Name { get; set; }
    public string Family { get; set; }
    public string Gender { get; set; }
}

Person myPerson = new Person();

var Json = (new
{
   Person = myPerson
});  

return Request.CreateResponse(HttpStatusCode.OK, Json);

It returns ID, Name, Family, Gender. I need to return only the Name and Family. I thought I can create an object and add my specific fields in the class in that object and return object?

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Behnam8
  • 65
  • 2
  • 9
  • Have you tried to search an answer in the site? https://stackoverflow.com/questions/10169648/how-to-exclude-property-from-json-serialization You should use [ScriptIgnore] attribute – Mauro Bilotti Oct 21 '19 at 18:21
  • Can you add the ignore attribute? Also all `json` libraries have this kind of attribute, which one are you working with? – Trevor Oct 21 '19 at 18:22
  • 3
    Possible duplicate of [Exclude certain fields when returning as json](https://stackoverflow.com/questions/32037555/exclude-certain-fields-when-returning-as-json) – Heretic Monkey Oct 21 '19 at 18:24
  • Çöđěxěŕ : I can't ignore it because I need that field in another json return – Behnam8 Oct 21 '19 at 18:25
  • @HereticMonkey yes that's the same question, but does not have the right anwer – Behnam8 Oct 21 '19 at 18:27
  • Sure it does. If you don't want to ignore the properties on the Person class, create a new class with just the properties you want to expose. That's mentioned in the second answer. – Heretic Monkey Oct 21 '19 at 18:29
  • @Behnam8 can't you derive a new class from `Attribute` and handle this maybe? – Trevor Oct 21 '19 at 18:31
  • @HereticMonkey Thanks for your answer, That's a solution. But I thought maybe there is a better solution. Because for large classes and Apps It's a little hard to create multiple classes with almost the same structure – Behnam8 Oct 21 '19 at 18:33
  • You could use a custom contract resolver. See e.g. `JsonConditionalIncludeContractResolver` from [Conditional member serialization based on query parameter?](https://stackoverflow.com/q/29713847/3744182) or `IgnorableSerializerContractResolver` from [this answer](https://stackoverflow.com/a/14510134/3744182) to [Exclude property from serialization via custom attribute (json.net)](https://stackoverflow.com/q/13588022/3744182). In fact this may be a duplicate of one of those two, agree? – dbc Oct 21 '19 at 18:44
  • @dbc Thanks for your help, I will check it. But stmax's solved my situation. – Behnam8 Oct 21 '19 at 18:52

2 Answers2

1

Use anonymous types?

return Request.CreateResponse(HttpStatusCode.OK, new {Name = person.Name; Family = person.Family});
stmax
  • 6,506
  • 4
  • 28
  • 45
0

You should consider applying the DRY principle. The DRY principle is not "never write code twice", but rather that "every piece of knowledge must have a single, unambiguous, authoritative representation in the system". What this means is that you have to build a model that has a meaningful name, contains properties that it actually has, and can be changed as needed later without having to figure out where else in the application it's used. I'm certain you could also find a name that would better represent this area of the application.

Should I create a different model with just the properties I need or use the same model and have NULL values for the field I don't use? Or just create anonymous type and make this way harder in future?

I don't recommend using the same model for your case, from my understanding of it. It's going to make your life easier down the road if you build a model that has a meaningful name as I said before.

So what should we do? I have seen many people trying to use JsonIgnore in domain model but you should not get down that path. You should avoid using JsonIgnore in domain model. I will give an example for it.

For example:

class Person {
    public int Id { get; set; }
    public string Name { get; set; }
    public string Family { get; set; }
    public string Gender { get; set; }
}

So you have this model and you want other models to inherit from it but like in your case you don't want to return Id and Gender, only Name and Family. So you go like this.

    class Person {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual string Family { get; set; }
        public virtual string Gender { get; set; }
    }

    public class PersonNameModel : Person {
         [JsonIgnore]
         public override int Id { get; set; }
         [JsonIgnore]
         public override string Gender{ get; set; }
    }

If a class has many properties and you only want to serialize a small subset of them then adding JsonIgnore to all the others will be tedious and error prone. The way to tackle this scenario is to add the DataContractAttribute to the class and DataMemberAttributes to the properties to serialize. This is opt-in serialization, only the properties you mark up with be serialized, compared to opt-out serialization using JsonIgnoreAttribute.

But, you can do it with the help of JsonIgnore 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 is a great solution. It gives me a clean REST API. At the same time when I save the data in a no-sql, the ignored properties are persisted despite the objects being stored as json.

[DataContract]
public class Person {
            public virtual int Id { get; set; }
            public virtual string Name { get; set; }
            public virtual string Family { get; set; }
            public virtual string Gender { get; set; }
}
public class PersonNameModel : Person {
            // included in JSON
            [DataMember]
            public override string Name { get; set; }
            [DataMember]
            public override string Family { get; set; }

            // other inherited properties will be ignored
}

I will also mention another way of doing it as there are more (custom contact resolver, Web API convention ("ShouldSerialize")...)

Another way you can do it is to decorate your auto property with JsonProperty attribute in order to skip the serialization of that field if it is null. Example:

class Person {
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public int? Id { get; set; }
        public string Name { get; set; }
        public string Family { get; set; }
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string Gender { get; set; }
    }

Happy coding!