【问题标题】:Parse JSON into Object将 JSON 解析为对象
【发布时间】:2026-02-22 02:20:05
【问题描述】:

我有一个User 类定义为:

User.java

package model;

import java.util.List;
import java.util.Map;

public class User {
    private final Map<String, List<String>> accountTransactionsMap;

    public User(final Map<String, List<String>> accountTransactionsMap) {
        this.accountTransactionsMap = accountTransactionsMap;
    }

    public Map<String, List<String>> getAccountTransactionsMap() {
        return accountTransactionsMap;
    }
}

我正在调用返回以下响应的 REST API:

{  
   "username1":{  
      "456":[  

      ],
      "123":[  

      ],
      "789":[  

      ]
   },
   "username2":{  
      "123":[  

      ],
      "456":[  

      ],
      "789":[  

      ]
   },
   "username3":{  
      "789":[  

      ],
      "123":[  

      ],
      "456":[  
         "transaction10",
         "transaction6",
         "transaction9",
         "transaction3"
      ]
   }
}

我希望能够解析响应并将其存储在 User 对象中。

我尝试了以下方法:

Test.java

public class Test {
    public static void main(final String[] args) {
        final String response = "{\"username1\":{\"456\":[],\"123\":[],\"789\":[]},\"username2\":{\"123\":[],\"456\":[],\"789\":[]},\"username3\":{\"789\":[],\"123\":[],\"456\":[\"transaction10\",\"transaction6\",\"transaction9\",\"transaction3\"]}}";
        final Gson gson = new Gson();
        final Type map = new TypeToken<Map<String, User>>(){}.getType();
        final Map<String, User> result = gson.fromJson(response, map);
        System.out.println(result);

        if (result != null) {
            for (final Map.Entry<String, User> entry : result.entrySet()) {
                System.out.println("username: " + entry.getKey());
                final User user = entry.getValue();
                System.out.println("transactions: " + user.getAccountTransactionsMap());
            }
        }
    }
}

这会产生输出:

{username1=model.User@80ec1f8, username2=model.User@1445d7f, username3=model.User@6a396c1e}
username: username1
transactions: null
username: username2
transactions: null
username: username3
transactions: null

我期望输出:

{username1=model.User@80ec1f8, username2=model.User@1445d7f, username3=model.User@6a396c1e}
username: username1
transactions: {123=[],456=[],789=[]}
username: username2
transactions: {123=[],456=[],789=[]}
username: username3
transactions: {123=[],456=["transaction10", "transaction6", "transaction9", "transaction3"],789=[]}

如何将accountIdtransactionIds 列表作为User 类中的变量解析到自己的映射中?

编辑:我想问题真的变成了,如何为我的User 类创建自定义TypeToken

【问题讨论】:

    标签: java json parsing gson


    【解决方案1】:

    您需要使用Map&lt;String, Map&lt;String, List&lt;String&gt;&gt;&gt;,而不是User 类:

    import com.google.gson.Gson;
    import com.google.gson.reflect.TypeToken;
    
    import java.io.File;
    import java.io.FileReader;
    import java.lang.reflect.Type;
    import java.util.List;
    import java.util.Map;
    
    public class GsonApp {
    
        public static void main(String[] args) throws Exception {
            File jsonFile = new File("./resource/test.json").getAbsoluteFile();
    
            final Gson gson = new Gson();
            final Type map = new TypeToken<Map<String, Map<String, List<String>>>>(){}.getType();
            final Map<String, Map<String, List<String>>> result = gson.fromJson(new FileReader(jsonFile), map);
            System.out.println(result);
    
            if (result != null) {
                for (final Map.Entry<String, Map<String, List<String>>> entry : result.entrySet()) {
                    System.out.println("username: " + entry.getKey());
                    final Map<String, List<String>> user = entry.getValue();
                    System.out.println("transactions: " + user);
                }
            }
        }
    }
    

    上面的代码打印:

    {username1={456=[], 123=[], 789=[]}, username2={123=[], 456=[], 789=[]}, username3={789=[], 123=[], 456=[transaction10, transaction6, transaction9, transaction3]}}
    username: username1
    transactions: {456=[], 123=[], 789=[]}
    username: username2
    transactions: {123=[], 456=[], 789=[]}
    username: username3
    transactions: {789=[], 123=[], 456=[transaction10, transaction6, transaction9, transaction3]}
    

    如果确实需要,可以在解析后创建User对象。

    【讨论】:

    • 谢谢,这段代码可以正常工作,但是如果 JSON 响应发生变化,则很难维护。我将编辑我的帖子,询问是否有办法为类定义自定义 TypeToken,以便我可以传递 TypeToken&lt;User&gt; 或类似的东西。
    • @rahattack,您可以尝试编写自定义反序列化器,就像在此question 中指出的那样。如果您可以使用Jackson,不妨试试。它有更好的反序列化选项。请参阅此question。你有架构喜欢:dynamic-key->dynamic-key->array 它可能看起来很奇怪,但它是非常正常的结构,我们可以使用 Maps 和 Lists 来处理。
    • Jackson 正是我想要的。感谢您的建议!