Gson 未正确将 LinkedHashMap 转换为 JSON

Gson doesn't properly convert a LinkedHashMap to JSON

提问人:Famro Fexl 提问时间:11/16/2023 最后编辑:Famro Fexl 更新时间:11/17/2023 访问量:65

问:

当我使用 GSON 将 LinkedHashMap 直接转换为 Json 时,它可以正确转换,但是当我将其转换为类字段时,它无法正确转换。在我正在研究的另一个案例中,只有 LinkedHashMap 的最后一个元素出现在最终的 Json 中。

public class Example {
    public static void main(String[] args) {
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        System.out.println("GSON HashMap!");
        System.out.println(gson.toJson(hashMe()));
        System.out.println("GSON Zone!");

        //This doesn't give me the full LinkedHashMap
        System.out.print(gson.toJson(zoneMe()));
    }
    
    public ZoneChild zoneMe() {
        RateChild rate = new RateChild(hashMe());
        ZoneChild zone = new ZoneChild();
        zone.setName("Example");
        zone.setRate(rate);
        return zone;
    }
    
    public LinkedHashMap<Integer, String> hashMe() {
        LinkedHashMap<Integer, String> rates = new LinkedHashMap<Integer, String>();
        rates.put(60, "data1");
        rates.put(25, "data2");
        rates.put(15, "data3");
        
        return rates;
    }
    
    public class Zone {
        RateChild rate;
        
        public Zone() {
        }
        
        public void setRate(RateChild rate) {
            this.rate = rate;
        }
    }
    
    public class ZoneChild extends Zone {
        private int level;
        private String name;
        
        public ZoneChild() {    
        }
        
        public void setName(String name) {
            this.name = name;
        }
        
        public void setLevel(int level) {
            this.level = level;
        }
    }
    
    public class Rate {
        LinkedHashMap<Integer, String> rate = new LinkedHashMap<Integer, String>();
        
        public Rate(LinkedHashMap<Integer, String> rate) {
            this.rate = rate;
        }
    }

    //I need this class for specialization
    public class RateChild extends Rate {
        
        public RateChild(LinkedHashMap<Integer, String> rate) {
            super(rate);
        }
    }
}

输出如下所示:

GSON HashMap!
{
  "60": "data1",
  "25": "data2",
  "15": "data3"
}
GSON Zone!
{
  "level": 0,
  "name": "Example",
  "rate": {
    "rate": {}
  }
}

我注意到当 LinkedHashMap 字段直接位于 Json 转换的类 (ZoneChild) 中时,它不会失败。

java json gson linkedhashmap

评论

1赞 experiment unit 1998X 11/16/2023
难道不是因为你没有对传递给 Rate 的 LinkedHashMap 做任何事情吗?GSON 只看到它没有变化,因此返回空速率LinkedHashMap<Integer, String> rate = new LinkedHashMap<Integer, String>();
0赞 Slaw 11/16/2023
也就是说,如果您更改 to or 的构造函数,那么您的代码应该按预期工作。Ratethis.rate = ratethis.rate.putAll(rate)
0赞 Famro Fexl 11/16/2023
@Slaw 对不起,我忘了。不,那不是问题。只是一个错别字。
0赞 experiment unit 1998X 11/16/2023
那么这可能是由于 Rate 的可见性。Zone 将 Rate 指定为默认可见性,但需要对其进行保护或公开,才能对 ZoneChild 可见
1赞 Rob 11/17/2023
问题有太多的代码。优化它:只添加代码中不能正常工作的部分 - 调试你的代码,看看在代码解释的某个时间发生了什么。如果它没有帮助,请使用打开的调试器截取屏幕截图,并向您提出一些更有价值的信息。仅仅把你所有的代码都放在这里并不能帮助社区正确回答,许多人甚至在不太复杂的问题中看起来没有那么复杂的代码库。希望它会有所帮助。

答:

0赞 Slaw #1

无法重现。使用 Java 21.0.1 和 Gson 2.10.1,以下代码按预期工作:

import java.util.LinkedHashMap;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class Main {

    public static void main(String[] args) {
        LinkedHashMap<Integer, String> data = new LinkedHashMap<>();
        data.put(60, "data1");
        data.put(25, "data2");
        data.put(15, "data3");

        Zone zone = new ZoneChild(new RateChild(data), "Example", 0);
        System.out.printf("##########  Original   ##########%n%n%s%n%n", zone);

        Gson gson = new GsonBuilder().setPrettyPrinting().create();

        String jsonStr = gson.toJson(zone);
        System.out.printf("########## JSON String ##########%n%n%s%n%n", jsonStr);

        Zone decoded = gson.fromJson(jsonStr, ZoneChild.class);
        System.out.printf("##########   Decoded   ##########%n%n%s%n", decoded);
    }

    public static class Zone {

        RateChild rate;

        public Zone() {}

        public Zone(RateChild rate) {
            this.rate = rate;
        }

        @Override
        public String toString() {
            return String.format("Zone[rate=%s]", rate);
        }
    }

    public static class ZoneChild extends Zone {

        String name;
        int level;

        public ZoneChild() {}

        public ZoneChild(RateChild rate, String name, int level) {
            super(rate);
            this.name = name;
            this.level = level;
        }

        @Override
        public String toString() {
            return String.format("ZoneChild[rate=%s, name=%s, level=%d]", rate, name, level);
        }
    }

    public static class Rate {

        LinkedHashMap<Integer, String> data;

        public Rate() {}

        public Rate(LinkedHashMap<Integer, String> data) {
            this.data = data;
        }

        @Override
        public String toString() {
            return String.format("Rate[data=%s]", data);
        }
    }

    public static class RateChild extends Rate {

        public RateChild() {}

        public RateChild(LinkedHashMap<Integer, String> data) {
            super(data);
        }

        @Override
        public String toString() {
            return String.format("RateChild[data=%s]", data);
        }
    }
}

输出:

##########  Original   ##########

ZoneChild[rate=RateChild[data={60=data1, 25=data2, 15=data3}], name=Example, level=0]

########## JSON String ##########

{
  "name": "Example",
  "level": 0,
  "rate": {
    "data": {
      "60": "data1",
      "25": "data2",
      "15": "data3"
    }
  }
}

##########   Decoded   ##########

ZoneChild[rate=RateChild[data={60=data1, 25=data2, 15=data3}], name=Example, level=0]