繁体   English   中英

Gson.toJson() 乱序项目

[英]Gson.toJson() misordering items

我有这个输出JSON:

{
  "id": 42950262095,
  "name": "lol",
  "players": [
    {
      "avatar": {
        "userId": 25771876384,
        "userName": "yhht",
        "role": "Leader",
        "level": 40,
        "league": 0,
        "trophies": 1011,
        "donatedTroops": 0,
        "receivedTroops": 0
      }
    },
    {
      "avatar": {
        "userId": 146035414262,
        "userName": "ari",
        "role": "New Member",
        "level": 8,
        "league": 0,
        "trophies": 428,
        "donatedTroops": 0,
        "receivedTroops": 0
      }
    },
    {
      "avatar": {
        "userId": 300659467521,
        "userName": "cp 221",
        "role": "New Member",
        "level": 6,
        "league": 0,
        "trophies": 97,
        "donatedTroops": 0,
        "receivedTroops": 0
      }
    }
  ],
  "badge": 13000049,
  "status": "Anyone Can Join",
  "playerCount": 3,
  "score": 767,
  "requiredTrophies": 0,
  "warsWon": 0,
  "warsLost": 0,
  "warsTied": 0,
  "warFrequency": 0,
  "exp": 0,
  "level": 1,
  "description": "??lol????"
}

但问题是玩家数组来得太早,部分初始细节被遗漏了。

这是我的代码:

public void parseAvatar() throws IOException, JSONException{

        Game game = new Game();

        game.setId(is.readLong());
        game.setName(is.readString());
        game.setBadge(is.readInt());
        game.setStatus(status(is.readInt()));
        game.setPlayerCount(is.readInt());
        game.setScore(is.readInt());
        game.setRequiredTrophies(is.readInt());
        game.setWarsWon(is.readInt());
        game.setWarsLost(is.readInt());
        game.setWarsTied(is.readInt());
        is.readInt();
        game.setWarFrequency(is.readInt());
        is.readInt();
        game.setExp(is.readInt());
        game.setLevel(is.readInt());
        game.setDescription(is.readString());
        is.readInt();
        boolean a = is.readBoolean();

        if(a){
            is.readInt();
            is.readInt();
        }

        int memCount = is.readInt();
        /// Members!!

        int i = 0;
        while(i < memCount){
            PlayerAvatar avatar = new PlayerAvatar();
            avatar.setUserId(is.readLong());
            avatar.setUserName(is.readString());
            avatar.setRole(role(is.readInt()));
            avatar.setLevel(is.readInt());
            avatar.setLeague(is.readInt());
            avatar.setTrophies(is.readInt());
            avatar.setDonatedTroops(is.readInt());
            avatar.setReceivedTroops(is.readInt());
            is.readInt();
            is.readInt();
            is.readLong();
            is.readByte();
            is.readByte();
            is.readLong();

            GamePlayer player = new GamePlayer();
            player.setAvatar(avatar);
            game.addPlayers(player);
            i++;
        }


        json = new Gson().toJson(game);
        System.out.println();
    }


    private String role(int role) {
        String memberRole = "";

        if(role == 1){
            memberRole = "New Member";
        }   

        if(role == 2){
            memberRole = "Leader";
        }   

        if(role == 3){
            memberRole = "Elder";
        }   

        if(role == 4){
            memberRole = "Co Leader";
        }   

        return memberRole;
    }

    private String status(int statusint) {
        String type = null;
        if(statusint == 1){
            type = "Anyone Can Join";
        }
        if(statusint == 2){
            type = "Invite Only";
        }
        if(statusint == 3){
            type = "Closed";
        }
        return type;
    }

您可以在这篇文章中找到 Game、PlayerAvatar 和 GamePlayer 类的详细信息: https ://stackoverflow.com/a/33048622

有没有人知道我如何正确订购它?

JSON 对象根据定义是无序的 - 您不应该依赖属性的顺序。 所以gson正在做的事情非常好。

如果由于某种原因你别无选择只能依赖排序,那么这个问题有一些解决方案: 如何在 Gson 序列化中保持字段序列(例如使用 jackson 而不是 gson 并使用@JsonPropertyOrder ,或实现自定义序列化程序)。

使用当前的gson 和 JDK 实现,重新排序类中的成员将产生相应顺序的输出,但是这是一个非常脆弱的解决方案。 例如

  • JDK 不保证通过反射读取字段的顺序,并且将来可能会更改(过去已更改),这会破坏您的代码。 (这实际上是最不可能的问题,但它是可能的)。 事实上 ,JDK 8 文档明确指出

    返回的数组中的元素没有排序,也没有任何特定的顺序

  • 即使 JDK 的顺序没有改变,gson 也不保证它会以相同的顺序返回它们。 它目前确实以相同的顺序返回它们,但是如果由于某种原因 gson 的内部结构发生了变化,例如使用中间HashMap ,则顺序会改变并且您的代码会中断。
  • 如果将来有其他人在维护您的类,他们会非常惊讶地发现仅对类中的字段重新排序会破坏代码 - Java 类中的字段排序不应改变功能。

如果您只是为了自己的娱乐而编写代码,或者使用一次来转换某些数据,那可能没什么大不了的,但是如果您正在编写其他人(甚至未来的你)需要维护的代码,我强烈建议建议您编写不依赖于假设层和/或不断测试的代码,以确保多个未记录的行为没有改变。

现在花几分钟合并代码以实际保证字段的顺序可以节省数小时或数天的调试时间。 这发生在现实生活中所有的时间

Gson根据你对象的字段声明顺序创建json字符串(因为它使用Java reflection ordering ,反射字段在jdk 6上确实按照它们的声明顺序,但在jdk 7之后改变了)

确保您的 JDK 是 6。Gson 至少是 2.2.4 版本。

private Long id;
private String name;
private List<Player> players;

打印为 json 字符串:第一个 ID,然后是玩家。

{
  "id": 171799578198,
  "name": "Forum Striking",
  "players": [
    {
      "avatar": {
        "userId": 21393,
        "currentHomeId": 21393,
        "clanId": 171799578198
      }
    },
    {
      "avatar": {
        "userId": 64425223942,
        "currentHomeId": 64425223942,
        "clanId": 171799578198
      }
    }
  ]
}

private Long id;
private List<Player> players;
private String name;

最后打印为 json 字符串:id、玩家和姓名。

{
  "id": 171799578198,
  "players": [
    {
      "avatar": {
        "userId": 21393,
        "currentHomeId": 21393,
        "clanId": 171799578198
      }
    },
    {
      "avatar": {
        "userId": 64425223942,
        "currentHomeId": 64425223942,
        "clanId": 171799578198
      }
    }
  ],
  "name": "Forum Striking"
}

因此,您应该在游戏对象的末尾声明玩家列表。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM