Attributes
If you want an attribute on your model to be publicly available, add the AttrAttribute
.
#nullable enable
public class Person : Identifiable<int>
{
[Attr]
public string? FirstName { get; set; }
[Attr]
public string LastName { get; set; } = null!;
}
Name
There are two ways the exposed attribute name is determined:
Using the configured naming convention.
Individually using the attribute's constructor.
#nullable enable
public class Person : Identifiable<int>
{
[Attr(PublicName = "first-name")]
public string? FirstName { get; set; }
}
Capabilities
since v4.0
Default JSON:API attribute capabilities are specified in JsonApiOptions:
options.DefaultAttrCapabilities = AttrCapabilities.None; // default: All
This can be overridden per attribute.
AllowView
Indicates whether the attribute value can be returned in responses. When not allowed and requested using ?fields[]=
, it results in an HTTP 400 response.
Otherwise, the attribute is silently omitted.
#nullable enable
public class User : Identifiable<int>
{
[Attr(Capabilities = ~AttrCapabilities.AllowView)]
public string Password { get; set; } = null!;
}
AllowFilter
Indicates whether the attribute can be filtered on. When not allowed and used in ?filter=
, an HTTP 400 is returned.
#nullable enable
public class Person : Identifiable<int>
{
[Attr(Capabilities = AttrCapabilities.AllowFilter)]
public string? FirstName { get; set; }
}
AllowSort
Indicates whether the attribute can be sorted on. When not allowed and used in ?sort=
, an HTTP 400 is returned.
#nullable enable
public class Person : Identifiable<int>
{
[Attr(Capabilities = ~AttrCapabilities.AllowSort)]
public string? FirstName { get; set; }
}
AllowCreate
Indicates whether POST requests can assign the attribute value. When sent but not allowed, an HTTP 422 response is returned.
#nullable enable
public class Person : Identifiable<int>
{
[Attr(Capabilities = AttrCapabilities.AllowCreate)]
public string? CreatorName { get; set; }
}
AllowChange
Indicates whether PATCH requests can update the attribute value. When sent but not allowed, an HTTP 422 response is returned.
#nullable enable
public class Person : Identifiable<int>
{
[Attr(Capabilities = AttrCapabilities.AllowChange)]
public string? FirstName { get; set; };
}
Complex Attributes
Models may contain complex attributes.
Serialization of these types is done by System.Text.Json,
so you should use their APIs to specify serialization format.
You can also use global options to control the JsonSerializer
behavior.
#nullable enable
public class Foo : Identifiable<int>
{
[Attr]
public Bar? Bar { get; set; }
}
public class Bar
{
[JsonPropertyName("compound-member")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? CompoundMember { get; set; }
}
If you need your complex attributes persisted as a
JSON string in your database, but you need access to it as a concrete type, you can define two members on your resource.
The first member is the concrete type that you will directly interact with in your application. You can use the NotMapped
attribute to prevent Entity Framework Core from mapping it to the database. The second is the raw JSON property that will be persisted to the database. How you use these members should determine which one is responsible for serialization. In this example, we only serialize and deserialize at the time of persistence
and retrieval.
#nullable enable
public class Foo : Identifiable<int>
{
[Attr]
[NotMapped]
public Bar? Bar { get; set; }
public string? BarJson
{
get
{
return Bar == null ? "{}" : JsonSerializer.Serialize(Bar);
}
set
{
Bar = string.IsNullOrWhiteSpace(value)
? null
: JsonSerializer.Deserialize<Bar>(value);
}
}
}