Assign Jackson-Jsog's #id to a member variable - jackson

Is it possible to assign the jsog's #id value to an member variable in a POJO class?
For example I have a json:
"user": {
"#id": "1",
"name": "John Doe"
}
And Java class
#JsonIdentityInfo(generator=JSOGGenerator.class)
public class User {
private String id; // this is null
private String name;
// getters and setters ...
}
I tried #JsonProperty("#id") but it my id still is null. Does anyone have an experience with this? I don't want to add another id field into my JSON as it makes it ugly.
Thank you in advance.

The identifier "#id" is not a valid Java property since it begins the '#' character. This is a nice feature since it won't conflict with any properties you have on your object.
I'm not sure how you transform that property into a Java property but you probably don't want to. The #id is purely for serialization/deserialization of the object graph; the #id value may change with each serialization if the object graph has changed.
You can't use the #id as an identifier of a object in a meaningful way outside of the serialization. You probably want a real ID that doesn't change based on serialization.

Related

Send JSON with list to Controller

I am trying to send following JSON to my controller:
[
{
"collection": "col1",
"uuid": [
"11:22:33:44:55:66",
"11:22:33:44:55:66"
]
},
{
"collection": "test"
}
]
Every object "collection" contains a list of strings symbolized by the uuids.
My model looks like this:
public class DummyDeviceApiModel {
[Display(Name = "UUID")]
[StringLength(36)]
public List<string> uuid {get; set;}
[Display(Name = "Collection")]
public string collection {get; set;}
}
and my controller function like this:
public async Task<ActionResult<DummyDeviceModel>> PostCreateDummyDevice(List<DummyDeviceApiModel> ddpm)
What works is when I just send the collection part, but the UUID with its list makes problem:
System.InvalidCastException: Unable to cast object of type
'System.Collections.Generic.List`1[System.String]' to type
'System.String'
.
Any idea what I am doing wrong? The issue seems to be the "second" list in the model.
Thanks
Stephan
[StringLength(36)] is a validation attribute for type string not arrays of string or List<string>. The exception is probably happening behind the scenes as it tries to validate on your property since it is of type List<string>. If you want to do what I think you do, create a custom validation on your list to make sure you only have strings in your list which are less than or equal to a length of 36, then you need to either implement IValidatableObject on your model (class) or create a custom Validation Attribute for validation by creating a class which inherits from ValidationAttribute. You can read more about how to implement this interface and/or create a custom attribute at MSDN: (https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-3.1). As a test to see if it is indeed the StringLength attribute which is throwing the exception, comment out that particular Validation Attribute in your code and see if it runs without error.

Why do we need the backing fields in EF Core?

Why do we need the backing fields in EF Core?
Why would someone want to use a field instead of a property while working with the entities? I can not come up with such a case. That probably means that I do not understand or I am missing something about the fields, since I thought that I could accomplish anything what is possible to do with the fields with the properties as well.
I am learning the EF Core through the tutorials over here.
Properties do not store anything. They are a pair of set and get methods. You must have a backing field to have them store something.
public class Data
{
private int _id; // Backing field used by property to store the value.
// Property whose name is used by EF Core to map to a column name.
public int Id
{
get { return _id; }
set { _id = value; }
}
... more properties
}
But you can simplify this code by using automatic properties
public class Data
{
// Auto-implemented property. Backing field and implementation are hidden.
public int Id { get; set; }
... more properties
}
This 2nd code snippet does exactly the same as the first one.
EF Core prefers backing fields over properties if their name can be inferred from the property name. The Conventions say:
By convention, the following fields will be discovered as backing fields for a given property (listed in precedence order). Fields are only discovered for properties that are included in the model. For more information on which properties are included in the model, see Including & Excluding Properties.
_<camel-cased property name>
_<property name>
m_<camel-cased property name>
m_<property name>

In ASPNetCore 2.2, Startup.cs, the Configure property only has {get}, yet it is assigned a reference. Why is this? [duplicate]

I created an automated property:
public int Foo { get; }
This is getter only.
But when I build a constructor, I can change the value:
public MyClass(string name)
{
Foo = 5;
}
Why is it possible, even though this is get-only?
This is a new C# 6 feature, "Getter-only auto-properties", also known as "Auto-Property Initializers for Read-Only Properties" as discussed in this MSDN magazine article 'C# : The New and Improved C# 6.0' by Mark Michaelis and in the C# 6.0 draft Language Specification.
The read-only field's setter is only accessible in the constructor, in all other scenarios the field is still read only and behaves as before.
This is a convenience syntax to reduce the amount of code you need to type and to remove the need to explicitly declare a private module level variable to hold the value.
This feature was seen as important as, since the introduction of Auto-Implemented Properties in C#3, mutable properties (those with a getter and setter) had become quicker to write than immutable ones (those with only a getter), meaning people were being tempted to use mutable properties to avoid having to type the code for a backing field usually required for read-only properties. There is more discussion of Auto-Implemented properties in the relevant section of the Microsoft C# Programming Guide.
This blog post, '#1,207 – C# 6.0 – Auto-Property Initializers for Read-Only Properties' by Sean Sexton Has a good explanation and example as follows:
Prior to C# 6.0, if you wanted a read-only (immutable) property, you’d
typically use a read-only backing field that is initialized in the
constructor, as shown below.
public class Dog
{
public string Name { get; set; }
// DogCreationTime is immutable
private readonly DateTime creTime;
public DateTime DogCreationTime
{
get { return creTime; }
}
public Dog(string name)
{
Name = name;
creTime = DateTime.Now;
}
}
In C# 6.0, you can use auto-implemented properties to implement a
read-only property. You do this by using an auto-property
initializer. The result is much cleaner than the above example, where
we had to explicitly declare a backing field.
public class Dog
{
public string Name { get; set; }
// DogCreationTime is immutable
public DateTime DogCreationTime { get; } = DateTime.Now;
public Dog(string name)
{
Name = name;
}
}
More details can also be found in the dotnet Roslyn repo on GitHub:
Auto-properties can now be declared without a setter.
The backing field of a getter-only auto-property is implicitly
declared as readonly (though this matters only for reflection
purposes). It can be initialized through an initializer on the
property as in the example above. Also, a getter-only property can be
assigned to in the declaring type’s constructor body, which causes the
value to be assigned directly to the underlying field:
This is about expressing types more concisely, but note that it also
removes an important difference in the language between mutable and
immutable types: auto-properties were a shorthand available only if
you were willing to make your class mutable, and so the temptation to
default to that was great. Now, with getter-only auto-properties, the
playing field has been leveled between mutable and immutable.
and in the C# 6.0 draft Language Specification (NB: The language specification is final as far as Microsoft are concerned, but it is yet to be approved as a EMCA/ISO standard, hence the 'draft'):
Automatically implemented properties
An automatically implemented property (or auto-property for short), is
a non-abstract non-extern property with semicolon-only accessor
bodies. Auto-properties must have a get accessor and can optionally
have a set accessor.
When a property is specified as an automatically implemented property,
a hidden backing field is automatically available for the property,
and the accessors are implemented to read from and write to that
backing field. If the auto-property has no set accessor, the backing
field is considered readonly (Readonly fields). Just like a readonly
field, a getter-only auto-property can also be assigned to in the body
of a constructor of the enclosing class. Such an assignment assigns
directly to the readonly backing field of the property.
An auto-property may optionally have a property_initializer, which is
applied directly to the backing field as a variable_initializer
(Variable initializers).
This is a new feature in C#6 that allows you to create read-only properties and initialize their values from the constructor (or inline when you declare them).
If you try to change the value of this property outside the constructor, it would give you a compile error.
It is read-only in the sense that once you initialize its value (inline or inside the constructor), you cannot change its value.
If it were not possible to initialize the read-only property from the constructor (or an auto-property initializer), then it would be useless, since it would always return the default value for its type (0 for numerics, null for reference types). The same semantics applied to readonly fields in all C# versions.
To define a true getter-only property (that cannot be initialized from the constructor), you need to specify what it returns as part of the definition:
public int Foo { get { return 5; } }
Or, more concisely in C# 6:
public int Foo => 5;
“readonly automatically implemented properties”
First of all I want to clarify that the property like
public string FirstName { get; }
Is known as “readonly automatically implemented properties”
To verify this you can run & check the above code with Visual Studio. If you change the language version from C#6.0 to C#5.0 then compiler will throw the following exception
Feature 'readonly automatically implemented properties' is not available in C# 5. Please use language version 6 or greater.
to change C# language version visit here
Now I am coming to your second question
“This is getter only. But when I build a constructor, I can change the value”
Microsoft introduces the “readonly automatically implemented properties” on the logic of read only. As we know that the keyword “readonly” is available from C#1.0. we use “readonly” keyword as modifier on a field and that field can be assigned in 2 ways either at the time of declaration or in a constructor in the same class.
In the same way value of “readonly automatically implemented properties” can be assigned in 2 ways
Way1 (at the time of declaration):
public string FirstName { get; } = "Banketeshvar";
Way2 (in a constructor in the same class)
Person()
{
FirstName = "Banketeshvar";
}
Purely ReadOnly Property
If you are looking for purely Readonly property then go for this
public string FullName => "Manish Sharma";
now you cannot assign value of “FullName” propery from constructor.
If you try to do that it will throw the following exceptions
“Property or indexer 'Person.FullName' cannot be assigned to -- it is read only”
Auto property feature was added to the language during C# 3.0 release. It allows you to define a property without any backing field, however you still need to use constructor to initialize these auto properties to non-default value. C# 6.0 introduces a new feature called auto property initializer which allows you to initialize these properties without a constructor like Below:
Previously, a constructor is required if you want to create objects
using an auto-property and initialize an auto-property to a
non-default value like below:
public class MyClass
{
public int Foo { get; }
public Foo(int foo)
{
Foo = foo;
}
}
Now in C# 6.0, the ability to use an initializer with the auto-property
means no explicit constructor code is required.
public string Foo { get; } = "SomeString";
public List<string> Genres { get; } = new List<string> { "Comedy", "Drama" };
You can find more information on this here
A variable declared readonly can be written within a constructor, but in languages which honor the attribute, cannot be modified after the constructor returns. That qualifier was provided as a language feature because it is often necessary for fields whose values will vary based upon constructor parameters (meaning they can't be initialized before the constructor starts) but won't have to change after constructors return, but it was only usable for variables exposed as fields. The semantics of readonly-qualified fields would in many cases have been perfect for public members except that it's often better for classes to expose members--even immutable ones--as properties rather than fields.
Just as read-write auto-properties exist to allow classes to expose mutable properties as easily as ordinary fields, read-only auto-properties exist to allow classes to expose immutable properties as easily as readonly-qualified fields. Just as readonly-qualified fields can be written in a constructor, so too with get-only properties.

Jackson deserialization: How to get a default value even if the JSON property was null

In my project I'm using Jersey 2.23.1 with Jackson for JSON support.
When I'm getting a request with something like { "foo":null, "bar":"123" } as JSON, matching with class A{String foo; String bar;} Jersey first creates and instance of A (with default values if specified in constructor), then deserialize JSON to a temporary object A', then copies all JSON fields that were specified in JSON from A' to A. If I have default values in A-class constructor, and have fields equal to null in JSON, all my default values are erased and replaced by null. So in the example above, if I have a default value for the foo field, it will be replaced by null in the object Jersey will return as param for my #Path annotated method.
I'm using #JsonInclude(Include.NON_NULL) on A class to avoid the transfer of null fields during Response. But it only works for serialization, what about deserialization? I mean, when having { "foo":null } as JSON results in field "foo" = null in new object instance after deserialization.
Here is some code to sum all of this :
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(value = Include.NON_NULL)
public class User {
public enum EUserRole {
PARENT, STUDENT, PROF, ADMIN
}
#Id
public String id;
public String firstName;
public String lastName;
public EUserRole role;
public User() {
id = ObjectId.get().toString();
role = EUserRole.STUDENT;
lastName = "RandomLastName";
}
}
if I'm passing this kind of JSON
{
"id":null,
"lastName":null,
"firstName":"Random First Name",
"role":"STUDENT"
}
to my method (in controller)
#POST
public Response createUser(final User entity) {
}
it results that all null fields in JSON are set to null in my entity and not set to the constructor default values.
Do you know if there is a way to specify Jackson to ignore null fields during deserialization? Or is this a Jersey-related behavior?
There is no way to ignore data from JSON payload in that sense, based on value contained (you can use ignoral to just ignore all values for given property).
So if you want to avoid null assignment, you need define a setter that will just swallow null value (that is, only assign non-null).
Ability to prevent null assignment might a useful feature to add via #JsonFormat.Feature, something like:
// hypothetical no such feature exists yes
#JsonFormat(without = JsonFormat.Feature.ALLOW_NULL_ASSIGNMENT)
so perhaps this could be a feature request.
And the reason I think this belongs to per-property handling is that this seems like a specific rule for some of the properties. Although perhaps there could also be a matching global setting if it seems users really like such null-ignoral.

Why does Json.NET not include $type for the root object when TypeNameHandling is Auto?

When I set Json.NET to serialize with TypeNameHandling set to TypeNameHandling.Auto, it correctly sets $type for child properties of an object but does not do so for the root object being serialized. Why?
Please consider the following repro:
public class Animal
{
public Animal[] Offspring { get; set; }
}
public class Dog : Animal {}
Animal fido = new Dog
{
Offspring = new Animal[] { new Dog() }
};
var json = JsonConvert.SerializeObject(fido,
new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
The Json emitted into the json variable is:
{
"Offspring": [{
"$type": "MyApp.Dog, MyApp",
"Offspring": null
}]
}
The Json.NET Documentation says that for TypeNameHandling.Auto the behavior is:
Include the .NET type name when the type of the object being serialized is not the same as its declared type.
My question is - Why does fido not have
"$type": "MyApp.Dog, MyApp", like its puppy? :)
UPDATE: I've found out from the accepted answer to this question that I can force $type to be added by doing this:
var json = JsonConvert.SerializeObject(fido,
typeof(Animal),
new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
Formatting = Formatting.Indented
});
But my question still holds - Why does Json.NET not do this by itself as per the documentation?
Short answer: it doesn't because it can't.
As you stated in your question, setting TypeNameHandling to Auto directs Json.Net to include the .NET type name when the actual (run-time) type of the object being serialized is not the same as its declared (compile-time) type. In order to do that, Json.Net needs to know both types for every object.
For everything inside the root object, this is straightforward: just get the runtime type of the root object via GetType(), then use reflection to get all of its declared properties and their types, and for each one compare the declared type to the actual type to see if they differ. If they do, output the type name.
But for the root object itself, Json.Net doesn't have access to both types. All the information it has is the object referenced by fido, whose runtime type is Dog. There's no way for Json.Net to discover that the fido variable was declared as Animal, unless you provide that context somehow. And that is exactly why Json.Net provides overloads of SerializeObject which allow you to specify the compile-time type of the object being serialized. You must use one of these overloads if you want the TypeNameHandling.Auto setting to work for the root object.
Brian is absolutely correct, Json.NET has no way of knowing the compile-time declared type of the object it's being passed as the value parameter is declared as an object. The easy fix for this was if Json.NET added generic serialize methods so that the compile-time declared type would automatically flow over to Json.NET but the library's author has decided against my proposal for this here.
As an alternative, I've wrapped all my json (de)serialization needs in a JsonHelper class with generic serialize methods which use the typeof expression to automatically pass the compile-time declared type of the value to be serialized.
Newer versions of Json.Net allow you to pass the expected type to the serialize method
ser.Serialize(stream, rootObject, typeof(BaseClass));
You can pass the base class to the serialize method and TypeNameHandling.Auto will write the $type if the object and expected type do not match.