gson 反序列化递归嵌套对象的json

ia2d9nvy  于 2022-11-06  发布在  其他
关注(0)|答案(1)|浏览(196)

我尝试使用gson反序列化json,然后使用Room将其插入DB,但没有成功:

[
  {
    "id": 1,
    "name": "category1",
    "categories": [
      {
        "id": 2,
        "name": "category2",
        "count": 321
      },
      {
        "id": 3,
        "name": "category3",
        "categories": [
          {
            "id": 4,
            "name": "category4",
            "count": 20
          },
          {
            "id": 5,
            "name": "category5",
            "count": 205
          },
          {
            "id": 6,
            "name": "category6",
            "count": 85
          }
        ]
      }
    ]
  }
]

类别对象应包含:

  • id(唯一,必需)
  • 名称(必填)
  • 父标识
  • count(如果没有子项,则为内容大小)

请帮助我递归地解析这个并插入数据库。

eqoofvh9

eqoofvh91#

您需要做的是创建反映JSON的类,以便提取数据,然后从这些类中插入数据。
检查您提供的json,然后您可以:-
1.一个可以是主类别的数组,
1.类别数组,每个类别都可以有
1.返回一个类别数组。
但是,您似乎希望根据以下内容保存所有内容:-
类别对象应包含:id(唯一,必需)name(必需)parent_id count(如果没有子项,则为内容大小)
作为类别。
因此,考虑到这一点,主类将是Category(您希望将所有3种类型(主类别、类别和类别中的类别)存储到其中)
所以首先是一个MainCategory类:-

class MasterCategory {
   private long id;
   private String name;
   private List<Category> categories;

   public long getId() {
      return id;
   }

   public void setId(long id) {
      this.id = id;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public List<Category> getCategories() {
      return categories;
   }

   public void setCategories(List<Category> categories) {
      this.categories = categories;
   }
}

然后是一个Category类,它也是用于定义数据库中的表的类。这可以是:-

@Entity
class Category {
    @PrimaryKey
    private Long id = null;
    private String name;
    private long count;
    private Long parent = null;
    @Ignore
    private List<Category> categories = null;

    Category(){}
    @Ignore
    Category(Long id, String name, long count,Long parent, List<Category> categories) {
        this.id = id;
        this.name = name;
        this.count = count;
        this.parent = parent;
        this.categories = categories;
    }
    @Ignore
    Category(Long id, String name, long count, Long parent) {
        this.id = id;
        this.name = name;
        this.count = count;
        this.parent = parent;
        this.categories = null;
    }

    public long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public long getCount() {
        return count;
    }

    public void setCount(long count) {
        this.count = count;
    }

    public List<Category> getCategories() {
        return categories;
    }

    public void setCategories(List<Category> categories) {
        this.categories = categories;
    }

    public Long getParent() {
        return parent;
    }

    public void setParent(Long parent) {
        this.parent = parent;
    }
}
  • 您可能希望对此进行研究并参考相应的注解

为了支持数据库访问,您有一个@Dao注解类CategoryDao,例如(足以演示存储和检索):-

@Dao
abstract class CategoryDao {
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    abstract long insert(Category category);
    @Query("SELECT * FROM category")
    abstract List<Category> getAllCategories();
}

为了合并以上所有内容,从数据库方面来看,您有一个@Database注解类TheDatabase,例如:-

@Database(entities = {Category.class}, exportSchema = false, version = TheDatabase.DATABASE_VERSION)
abstract class TheDatabase extends RoomDatabase {
   public static final int DATABASE_VERSION = 1;
   public static final String DATABASE_NAME = "the_database.db";

   abstract CategoryDao getCategoryDao();

   private volatile static TheDatabase instance = null;
   public static TheDatabase getInstance(Context context) {
      if (instance == null) {
         instance = Room.databaseBuilder(context,TheDatabase.class,DATABASE_NAME)
                 .allowMainThreadQueries()
                 .build();
      }
      return instance;
   }
}
  • 请注意,为了方便和简洁起见,.allowMainThreadQueries已被编码(因此可以使用主线程进行演示)

最后,实际演示一个将使用JSON的活动,将所有三种类型(Master、Category和Categories)存储为一行,并带有相应的父级(即,Categories将以各自的MasterCategory id作为父级,Category中的categories将以Category的id作为父级)。
由于MasterCategory没有计数,因此计数将为0。
在演示中使用了gson库,如implementation 'com.google.code.gson:gson:2.9.0'。这允许非常简单的**getMasterCategoryListFromJSON方法,将JSON转换为MasterCategory数组。
另一个核心方法是
insertCategoriesFromMasterCategoryArray**。它接受MasterCategory[]并为所有三个级别/类型插入Category行。它返回插入ID的long[],或者如果插入被忽略,如果存在冲突(重复),则它将存储-1以指示。
因此,主要活动:-

public class MainActivity extends AppCompatActivity {

    String base = "[" +
            "  {" +
            " id: 1," +
            "    \"name\": \"category1\"," +
            "    \"categories\": [" +
            "      {" +
            "        \"id\": 2," +
            "        \"name\": \"category2\"," +
            "        \"count\": 321" +
            "      }," +
            "      {" +
            "        \"id\": 3," +
            "        \"name\": \"category3\"," +
            "        \"categories\": [" +
            "          {" +
            "            \"id\": 4," +
            "            \"name\": \"category4\"," +
            "            \"count\": 20" +
            "          }," +
            "          {" +
            "            \"id\": 5," +
            "            \"name\": \"category5\"," +
            "            \"count\": 205" +
            "          }," +
            "          {" +
            "            \"id\": 6," +
            "            \"name\": \"category6\"," +
            "            \"count\": 85" +
            "          }" +
            "        ]" +
            "      }" +
            "    ]" +
            "  }" +
            "]";
    TheDatabase db;
    CategoryDao dao;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        db = TheDatabase.getInstance(this);
        dao = db.getCategoryDao();

        MasterCategory[] mlist = getMasterCategoryListFromJSON(base);
        for (MasterCategory m: mlist) {
            Log.d("CATINFO","ID=" + m.getId() + " NAME=" + m.getName() + " it has " + m.getCategories().size() + " categories" );
        }
        long[] insertResult = insertCategoriesFromMasterCategoryArray(getMasterCategoryListFromJSON(base));
        for(Category c: dao.getAllCategories()) {
            Log.d("CATINFO", "ID = " + c.getId() + " NAME = " + c.getName() + " COUNT = " + c.getCount() + " PARENT = " + c.getParent());
        }
    }

    private MasterCategory[] getMasterCategoryListFromJSON(String json) {
        return new Gson().fromJson(json,MasterCategory[].class);
    }

    public long[] insertCategoriesFromMasterCategoryArray(MasterCategory[] mclist) {
        ArrayList<Long> rv = new ArrayList<>();
        Long currentMasterId = 0L;
        Long currentCategoryId = 0L;
        for (MasterCategory mc: mclist) {
            currentMasterId = dao.insert(new Category(mc.getId(),mc.getName(),0,null));
            rv.add(currentMasterId);
            for (Category c: mc.getCategories()) {
                c.setParent(currentMasterId);
                currentCategoryId = dao.insert(new Category(c.getId(),c.getName(),c.getCount(),c.getParent()));
                rv.add(currentCategoryId);
                if (c.getCategories() != null) {
                    for (Category sc : c.getCategories()) {
                        rv.add(dao.insert(new Category(sc.getId(), sc.getName(), sc.getCount(), currentCategoryId)));
                    }
                }
            }
        }
        long[] actualReturnValue = new long[rv.size()];
        for (int i = 0; i < rv.size(); i++) {
            actualReturnValue[i] = rv.get(i);
        }
        return actualReturnValue;
    }
}

运行时(这只是一个演示,因此只运行一次),它会将以下内容输出到日志中:-

D/CATINFO: ID=1 NAME=category1 it has 2 categories

D/CATINFO: ID = 1 NAME = category1 COUNT = 0 PARENT = null
D/CATINFO: ID = 2 NAME = category2 COUNT = 321 PARENT = 1
D/CATINFO: ID = 3 NAME = category3 COUNT = 0 PARENT = 1
D/CATINFO: ID = 4 NAME = category4 COUNT = 20 PARENT = 3
D/CATINFO: ID = 5 NAME = category5 COUNT = 205 PARENT = 3
D/CATINFO: ID = 6 NAME = category6 COUNT = 85 PARENT = 3

使用应用程序检查,则数据库为:-

相关问题