0

I serializing a list with flexjson. After serialization, I printing object hashcode() and I would check to see if the objects are equal.

Problem, after the operation the object reference are changing. I don't want it.

My code;

    String sameOfString="sameOfString";
    List<Object> list=new ArrayList<Object>();
    list.add(sameOfString);
    list.add(sameOfString);
    list.add("differentString");

    for(Object str:list){
        System.out.println(str.hashCode());
    }
    **System.out.println(list.get(0)==list.get(1));**
    System.out.println(list.get(0)==list.get(2));
    System.out.println("--");
    String json= new JSONSerializer().exclude("*.class").deepSerialize(list);
    List<String> listDeserilized = (List<String>) new JSONDeserializer().deserialize(json);
    for(Object str:listDeserilized){
        System.out.println(str.hashCode());
    }
    **System.out.println(listDeserilized.get(0)==listDeserilized.get(1));**
    System.out.println(listDeserilized.get(0)==listDeserilized.get(2));

And output..

1018069468

1018069468

199675306

true

false

-

1018069468

1018069468

199675306

false

false

How can solve this problem?

Gnosis00
  • 309
  • 6
  • 19

3 Answers3

1

I solved my problem with jackson lib.

@JsonIdentityInfo annotation protecting object relations(in other words; protecting references) and after deserialization, object locations dont changing in memory.

the final code :

package com.maar.projectbuilder;

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Firat on 11.9.2014.
 */
public class Testt {
    @JsonDeserialize(as=StringClazz.class)
    @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
    @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
    @JsonTypeName(value = "StringClazz")
    private static class StringClazz{
        private String data="";

        public StringClazz() {
        }

        public String getData() {
            return data;
        }

        public void setData(String data) {
            this.data = data;
        }
    }
    public static void main(String[] args) throws IOException {
        StringClazz someOfString=new StringClazz();
        someOfString.setData("someOfString");
        StringClazz differentString=new StringClazz();
        differentString.setData("differentString");

        List<StringClazz> list=new ArrayList<StringClazz>();
        list.add(someOfString);
        list.add(someOfString);
        list.add(differentString);

        for(Object str:list){
            System.out.println(str.hashCode());
        }
        System.out.println(list.get(0)==list.get(1));
        System.out.println(list.get(0)==list.get(2));
        System.out.println("-------");
        String json= null;
        try {
            json = new ObjectMapper().enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL).writeValueAsString(list);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        System.out.println(json);
        List<StringClazz> listDeserilized =new ObjectMapper().enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL).readValue(json, new TypeReference<List<StringClazz>>() {
        });
        for(Object str:listDeserilized){
            System.out.println(str.hashCode());
        }
        System.out.println(listDeserilized.get(0)==listDeserilized.get(1));
        System.out.println(listDeserilized.get(0)==listDeserilized.get(2));
    }
}
Gnosis00
  • 309
  • 6
  • 19
0

How can solve this problem?

You don't. Deserializing an object means creating a new instance, in a different location in memory.

However, and I don't recommend this, you can keep a registry of objects (a HashMap maybe), perform the deserialization, check if the registry contains the object, and replace it with the existing one.

The String class already already gives you some of this behavior with interning. See String#intern().

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • 1
    String.intern() will not allow the garbage collector to throw away memory when you stop using it. It is permanently in memory and can't be reclaimed. I'd highly suggest to avoid it if you want to build a stable and robust application. – chubbsondubs Sep 11 '14 at 16:26
0

What you are struggling with is what does it mean to be equal? In Java there are two versions of equality (as with many modern languages).

  1. Are these objects equal by value?
  2. Are these objects the same object? (ie by reference)

This is the difference between .equals() and == respectively. When you deserialize something it creates a new object and hence if you have another copy of that object you serialized. It will never be number 2 equal (ie equal by reference). Because the deserialization was given JSON representation and it created a new object graph from it.

But it could be .equals() provided your objects properly define what .equals() means for all objects included. By default Object.equals() compares references and is the same thing as ==. However, every object can overload it, and in the case of String.equals() compares the actual content of the strings.

So just change your code to use .equals() instead of == and you get what you expect:

System.out.println( list.get(0).equals( list.get(1) ) )
System.out.println( list.get(0).equals( list.get(2) ) )
chubbsondubs
  • 37,646
  • 24
  • 106
  • 138