Why after De-Serialization the object reference not same as it was before serilization.
ok let me Explain this
I am Having a String
string test = "TestString";
Now I do Serilization
DataContractJsonSerializer _DataContractJsonSerializer
= new DataContractJsonSerializer(typeof(string));
MemoryStream ms = new MemoryStream();
_DataContractJsonSerializer.WriteObject(ms, test);
var jsonString = Encoding.Default.GetString(ms.ToArray());
Now I do DeSerilization from jsonstring into actual value
MemoryStream ms1 =
new MemoryStream(Encoding.Unicode.GetBytes(jsonString));
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(string));
string DeseriliaedStrring = serializer.ReadObject(ms1) as string;
here in DeseriliaedStrring i got the actual value but if i check there reference they are not equal
bool isReferenceEqual = object.ReferenceEquals(DeseriliaedStrring, test);
Serialization creates copies of the object's values. Deserialization creates a completely new instance with the copied values.
Edit in response to your comment below: Deserialization doesn't call a constructor. If this is a problem, then override with ISerializable. This will serialise based on a call to ISerializable.GetObjectData and then call a particular constructor with SerializationInfo and StreamingContext fields.
When you serialize and deserialize an object, the deserialization will create an instance base on the serialized data. This is of course not the same instance as the original one, that seems fairly logical. After all, you have the following process:
You have an object instance
You create a string instance that is a representation of that object instance
You create an object instance based on the serialized data in the string
If you take into consideration that the original instance might have mutated, that the deserialization can happen in another process, even in another machine, it becomes quite clear that deserialization could not possibly return the original instance.
In this particular case, when the object is a String, you could imagine that the string interning would make the system reuse the old instance (if the deserialization happened within the same AppDomain). But that would probably* require DataContractJsonSerializer to be aware of this, which would make it unnecessarily complex.
*) I am actually not quite sure of exactly what part of the system that takes care of string interning.
Related
I'm trying to understand get_instance_id()
and I came across this line in the documentation:
This ID can be saved in EncodedObjectAsID, and can be used to retrieve
the object instance with #GDScript.instance_from_id.
I can't seem to understand what this statement means exaclty and how to use EncodedObjectAsID, could someone please provide a working example?
The EncodedObjectAsID follows a pattern called Boxing. Boxing is where you put a primitive value, like an int, into an object. This boxed primitive can now be used in an object oriented way. For example, you can pass the boxed int to a function that only takes objects (i.e. it applies Polymorphism):
func only_takes_object(obj: Object)
only_takes_object(123) # Error
var box = EncodedObjectAsID.new()
box.object_id = 123
only_takes_object(box) # Valid
This is how parts of the editor use the EncodedObjectAsId object.
In marshalls.cpp we can see that an encoded Object may be an integer ID or the whole object. When it is flagged as only an integer ID a EncodedObjectAsID object is created. This object is then converted to a Variant.
When adding a stack variable in editor_debugger_inspector.cpp a variant with a type of object is assumed to be and converted to an EncodedObjectAsID to fetch the referenced object's id.
Here's two more links that follow a similar pattern:
array_property_edit.cpp
scene_debugger.cpp
Note that Variant can be implicitly converted to an Object and Object::cast_to() only takes Objects.
This ID can be saved in EncodedObjectAsID, and can be used to retrieve the object instance with #GDScript.instance_from_id.
This sentence should be split into two independent clauses. It should read as
"The instance ID can be saved in an EncodedObjectAsID."
"The instance ID can be used to retrieve the object instance with #GDScript.instance_from_id()."
Note: You should not store an object's id in storage memory. There is no guarantee that an object's id will remain the same after restart.
The following code
void testReference() {
List<String> source = new ArrayList<>()
source.add("element")
List reference = (ArrayList)source // all ok, creates reference as types match
assertSame(source,reference)
List copyNotReference = (LinkedList)source // should fail on GroovyCastException, creates copy instead
assertNotSame(source,copyNotReference) // this works, copy is a different object
copyNotReference.add("second element")
println source
println copyNotReference
}
only works in Groovy. In Java it fails on attempt to cast ArrayList to LinkedList.
In Groovy it creates a LinkedList instance, calling constructor
public LinkedList(Collection<? extends E> c)
and copying source data to the new instance.
The test outputs
[element]
[element, second element]
That behaviour only occurs when casting types that are subtypes of collections.
Question
What Groovy mechanism is responsible for this unexpected behaviour?
Groovy allows coercion of objects via casting them (asType). This is implemented for collections.
See the source
Converts the given collection to another type. A default concrete
type is used for List, Set, or SortedSet. If the given type has
a constructor taking a collection, that is used. Otherwise, the
call is deferred to {#link #asType(Object,Class)}. If this
collection is already of the given type, the same instance is
returned.
I am exchanging JSON messages between Java and C# (and vice-versa).
In Java I use a java.time.Instant (JSR-310) to represent a point in time on the global timeline. In order to create a human readable date/time string in JSON, I convert my Instant as follows:
private static final DateTimeFormatter FORMATTER = ofPattern("yyyy-MM-dd'T'HH:mm:ssZ").withZone(ZoneId.systemDefault());
which generates the following output:
2017-04-28T19:54:44-0500
Now, on the message consumer side of things (C#) I wrote a custom Newtonsoft.Json.JsonConverter, which extends the abstract JsonCreationConvert class that contains the following overridden ReadJson() method:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
if (reader.TokenType == JsonToken.StartArray)
{
return JToken.Load(reader).ToObject<string[]>();
}
reader.DateParseHandling = DateParseHandling.None; // read NodaTime string Instant as is
serializer.Converters.Add(NodaConverters.InstantConverter);
// Load JObject from stream
var jObject = JObject.Load(reader);
// Create target object based on JObject
T target = Create(objectType, jObject);
// Populate the object properties
var writer = new StringWriter();
serializer.Serialize(writer, jObject);
using (var newReader = new JsonTextReader(new StringReader(writer.ToString())))
{
newReader.Culture = reader.Culture;
newReader.DateParseHandling = reader.DateParseHandling;
newReader.DateTimeZoneHandling = reader.DateTimeZoneHandling;
newReader.FloatParseHandling = reader.FloatParseHandling;
serializer.Populate(newReader, target);
}
return target;
}
Create() is an abstract method.
When I now convert this JSON string into a NodaTime.Instant (v2.0.0) by calling:
InstantPattern.General.Parse(creationTime).Value;
I get this exception:
NodaTime.Text.UnparsableValueException: The value string does not match a quoted string in the pattern. Value being parsed: '2017-04-28T19:54:44^-0500'. (^ indicates error position.)
If I pass a text literal "Z" (so no outputted offset "-0500" and Z is interpreted as 0 offset) the NodaTime.Serialization.JsonNet.NodaConverters.InstantConverter correctly reads without throwing an exception.
Looking into the GeneralPatternImpl I see:
internal static readonly InstantPattern GeneralPatternImpl = InstantPattern.CreateWithInvariantCulture("uuuu-MM-ddTHH:mm:ss'Z'");
Why does an InstantConverter require the offset to be a text literal? Is this happening because an Instant is agnostic to an offset? If this is the case, then why doesn't the InstantConverter just ignore the offset instead of throwing an exception? Do I need to write a custom converter to get around this problem?
That's like asking for 2017-04-28T19:54:44 to be parsed as a LocalDate - there's extra information that we'd silently be dropping. Fundamentally, your conversion from Instant to String in Java is "adding" information which isn't really present in the original instant. What you're ending up with is really an OffsetDateTime, not an Instant - it has more information than an Instant does.
You should decide what information you really care about. If you only care about the instant in time, then change your Java serialization to use UTC, and it should end up with Z in the serialized form, and all will be well. This is what I suggest you do - propagating irrelevant information is misleading, IMO.
If you actually care about the offset in the system default time zone, which your call to .withZone(ZoneId.systemDefault()) implies you do, then you should parse it as an OffsetDateTime on the .NET side of things. You can convert that to an Instant afterwards if you want to (just call ToInstant()).
I have started using NSIncrementalStore. When you process a fetch request, you first have to process the predicate to get your internal reference objects. Then you convert these to objectID's and then you ask the context to get the corresponding managedObjects. At least that is my interpretation of the available documentation.
let fetchedReferences : [Int] = Array(names.keys) //names represent my backingstore
var fetchedObjectIDs : [NSManagedObjectID] = []
for reference in fetchedReferences
{
fetchedObjectIDs.append(self.newObjectIDForEntity(request.entity, referenceObject: reference))
}
var fetchedObjects : [NSManagedObject] = []
for objectID in fetchedObjectIDs
{
fetchedObjects.append(context.objectWithID(objectID))
}
"newObjectIDForEntity" is also used to obtain permanent objectID's (see obtainPermanentIDsForObjects)
I want to know what "newObjectIDForEntity" does. Does it make a new instance for the same object or does it each time internally create a new object? What I mean is this: if I create a new managed object and then fetch the object, I will have called "newObjectIDForEntity" twice for the same object. Does core data now think there are 1 or 2 objects?
Does it make a new instance for the same object or does it each time internally create a new object?
newObjectIDForEntity:referenceObject: is one of two utility methods for mapping between the store's internal representation of a managed object snapshot and an NSManagedObjectID. It's inverse is referenceObjectForObjectID:. As you might guess from the name, newObjectIDForEntity:referenceObject: returns an object considered to have a retain count of 1. newObjectIDForEntity:referenceObject: calls an internal factory method for generating an NSManagedObjectID that is unique to that reference object in this persistent store. Once that has been done, referenceObjectForObjectID: can look up that NSManagedObjectID and return the reference object it represents.
What I mean is this: if I create a new managed object and then fetch the object, I will have called "newObjectIDForEntity" twice for the same object. Does core data now think there are 1 or 2 objects?
I assume you mean an NSManagedObjectContext that is using your store creates the managed object. You can call newObjectIDForEntity:referenceObject: as many times as you want, the NSManagedObjectID instance may be different, but the data it represents is unchanged. It will know that it points to the same reference object as an earlier call with the same reference data and entity description.
Can someone please explain to me how writer.toString would hold the customer data? It appears as though marshal(customer,writer) somehow modified the writer. Please see below, thanks:
Customer customer = new Customer();
customer.setId(42);
customer.setName("Bill Burke");
JAXBContext ctx = JAXBContext.newInstance(Customer.class);
StringWriter writer = new StringWriter();
ctx.createMarshaller().marshal(customer, writer);
[See here:]
String custString = writer.toString(); // how did writer suddenly take on value?
customer = (Customer)ctx.createUnmarshaller()
.unmarshal(new StringReader(custString));
StringWriter is a Writer-implementation that writes into a StringBuffer. When you call write(), you append to that StringBuffer. ToString() calls toString() on that StringBuffer and returns it.
Marshaller.marshal() just serializes the JAXB objects into XML, and writes them into the Writer (and thus into the StringBuffer). The StringReader in your second snippet then reads from the String created by StringBuffer.
I'm guessing that the reason writer is able to write the content is because the marshaller must have called a method inside the write object which changed whatever write points to. Therefore, after the marshal(), the writer references new data.
http://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html (see bottom)