簡體   English   中英

Flexjson或Gson:對象序列化后保護對象引用

[英]Flexjson or Gson : Protect object references after object serialization

我使用flexjson序列化列表。 序列化后,我打印對象hashcode()然后檢查對象是否相等。

問題,操作后對象參考正在更改。 我不要

我的代碼;

    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));

並輸出..

1018069468

1018069468

199675306

真正

-

1018069468

1018069468

199675306

如何解決這個問題?

我用傑克遜·李(Jackson lib)解決了我的問題

@JsonIdentityInfo批注保護對象關系(換句話說,保護引用),反序列化后,對象位置在內存中@JsonIdentityInfo更改。

最終代碼:

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));
    }
}

如何解決這個問題?

你不知道 反序列化對象意味着在內存中的其他位置創建一個新實例。

但是, 我不建議這樣做 ,您可以保留對象的注冊表(也許是HashMap ),進行反序列化,檢查注冊表是否包含對象,然后將其替換為現有的對象。

String類已經為您提供了一些使用Intern的行為。 參見String#intern()

您在努力奮斗是什么意思是平等? 在Java中,有兩個相等的版本(與許多現代語言一樣)。

  1. 這些對象的價值相等嗎?
  2. 這些對象是同一對象嗎? (即參考)

這分別是.equals()和==之間的區別。 反序列化某些對象時,它會創建一個新對象,因此,如果您擁有該對象的另一個副本,則會進行序列化。 它永遠不會等於2(即按引用相等)。 因為反序列化被賦予了JSON表示,並且它由此創建了一個新的對象圖。

但這可能是.equals(),前提是您的對象正確定義了.equals()對包括的所有對象的含義。 默認情況下,Object.equals()比較引用,並且與==相同。 但是,每個對象都可以重載它,對於String.equals()而言,它會比較字符串的實際內容。

因此,只需將您的代碼更改為使用.equals()而不是==,您將獲得期望的結果:

System.out.println( list.get(0).equals( list.get(1) ) )
System.out.println( list.get(0).equals( list.get(2) ) )

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM