У меня проблемы с «вложенными» десериализаторами gson для следующего json образца. Я застрял на несколько дней.
Здесь я использую 3 десериализатора для dept
, contact
, role
. dept
и role
находятся на одном уровне иерархии. contact
находится внутри dept
. Проблема в том, что я не могу извлечь содержимое внутреннего contact
.
{
"depts": {
"dept": [
{
"name": "IT1",
"contacts": {
"contact": [
{
"name": "CCC11"
},
{
"name": "CCC12"
}
]
}
},
{
"name": "IT2",
"contacts": {
"contact": [
{
"name": "CCC21"
}
]
}
}
]
},
"roles": {
"role": [
{
"name": "ADMIN"
},
{
"name": "MANAGER"
}
]
}
}
public class D_result {
public D_depts depts;
public D_roles roles;
}
public class D_depts {
// fixme: choose either (A) or (B)
// region - (A) not using deserializer
//
// public D_dept[] dept;
//
// endregion - (A) not using deserializer
// region - (B) using deserializer
private static final String TAG_dept = "dept";
public D_dept mD_dept;
public D_dept[] mD_deptList;
public void setD_dept(D_dept d_dept) {
mD_dept = d_dept;
}
public void setD_deptList(D_dept[] d_deptList) {
mD_deptList = d_deptList;
}
public static class D_deptsDeserializer implements JsonDeserializer<D_depts> {
@Override
public D_depts deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
D_depts depts = new Gson().fromJson(json, D_depts.class);
JsonObject jsonObject = json.getAsJsonObject();
if (jsonObject.has(TAG_dept)) {
JsonElement jsonElement = jsonObject.get(TAG_dept);
if (jsonElement.isJsonArray()) {
JsonArray array = jsonElement.getAsJsonArray();
D_dept[] values = new Gson().fromJson(array, D_dept[].class);
depts.setD_deptList(values);
} else if (jsonElement.isJsonObject()) {
JsonObject object = jsonElement.getAsJsonObject();
D_dept value = new Gson().fromJson(object, D_dept.class);
depts.setD_dept(value);
} else {
}
}
return depts;
}
}
// endregion - (B) using deserializer
}
public class D_dept {
public String name;
public D_contacts contacts;
}
public class D_contacts {
// fixme: choose either (A) or (B)
// // region - (A) not using deserializer
//
// public D_contact[] contact;
//
// // endregion - (A) not using deserializer
// region - (B) using deserializer
private static final String TAG_contact = "contact";
public D_contact mD_contact;
public D_contact[] mD_contactList;
public void setD_contact(D_contact d_contact) {
mD_contact = d_contact;
}
public void setD_contactList(D_contact[] d_contactList) {
mD_contactList = d_contactList;
}
public static class D_contactsDeserializer implements JsonDeserializer<D_contacts> {
@Override
public D_contacts deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
D_contacts contacts = new Gson().fromJson(json, D_contacts.class);
JsonObject jsonObject = json.getAsJsonObject();
if (jsonObject.has(TAG_contact)) {
JsonElement jsonElement = jsonObject.get(TAG_contact);
if (jsonElement.isJsonArray()) {
JsonArray array = jsonElement.getAsJsonArray();
D_contact[] values = new Gson().fromJson(array, D_contact[].class);
contacts.setD_contactList(values);
} else if (jsonElement.isJsonObject()) {
JsonObject object = jsonElement.getAsJsonObject();
D_contact value = new Gson().fromJson(object, D_contact.class);
contacts.setD_contact(value);
} else {
}
}
return contacts;
}
}
// endregion - (B) using deserializer
}
public class D_contact {
public String name;
}
public class D_roles {
// fixme: choose either (A) or (B)
// // region - (A) not using deserializer
//
// public D_role[] role;
//
// // endregion - (A) not using deserializer
// region - (B) using deserializer
private static final String TAG_role = "role";
public D_role mD_role;
public D_role[] mD_roleList;
public void setD_role(D_role d_role) {
mD_role = d_role;
}
public void setD_roleList(D_role[] d_roleList) {
mD_roleList = d_roleList;
}
public static class D_rolesDeserializer implements JsonDeserializer<D_roles> {
@Override
public D_roles deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
D_roles roles = new Gson().fromJson(json, D_roles.class);
JsonObject jsonObject = json.getAsJsonObject();
if (jsonObject.has(TAG_role)) {
JsonElement jsonElement = jsonObject.get(TAG_role);
if (jsonElement.isJsonArray()) {
JsonArray array = jsonElement.getAsJsonArray();
D_role[] values = new Gson().fromJson(array, D_role[].class);
roles.setD_roleList(values);
} else if (jsonElement.isJsonObject()) {
JsonObject object = jsonElement.getAsJsonObject();
D_role value = new Gson().fromJson(object, D_role.class);
roles.setD_role(value);
} else {
}
}
return roles;
}
}
// endregion - (B) using deserializer
}
public class D_role {
public String name;
}
private static String sJsonString = "{\"depts\":{\"dept\":[{\"name\":\"IT1\",\"contacts\":{\"contact\":[{\"name\":\"CCC11\"},{\"name\":\"CCC12\"}]}},{\"name\":\"IT2\",\"contacts\":{\"contact\":[{\"name\":\"CCC21\"}]}}]},\"roles\":{\"role\":[{\"name\":\"ADMIN\"},{\"name\":\"MANAGER\"}]}}";
private void vTest() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(D_depts.class, new D_depts.D_deptsDeserializer());
gsonBuilder.registerTypeAdapter(D_roles.class, new D_roles.D_rolesDeserializer());
gsonBuilder.registerTypeAdapter(D_contacts.class, new D_contacts.D_contactsDeserializer());
Gson gson = gsonBuilder.create();
D_result result = gson.fromJson(sJsonString, D_result.class);
// D_dept[] dDepts = result.depts.dept; // not using deserializer
D_dept[] dDepts = result.depts.mD_deptList; // using deserializer
if (dDepts != null) {
for (D_dept dept : dDepts) {
Log.d(TAG, dept.name);
D_contacts dContacts = dept.contacts;
// if (dContacts != null && dContacts.contact != null) { // not using deserializer
if (dContacts != null && dContacts.mD_contactList != null) { // using deserializer
// for (D_contact contact : dContacts.contact) { // not using deserializer
for (D_contact contact : dContacts.mD_contactList) { // using deserializer
Log.d(TAG+"dbg", dept.name + " " + contact.name);
}
}
else {
Log.d(TAG+"dbg", "Contacts unavailable");
}
}
}
// D_role[] dRoles = result.roles.role; // not using deserializer
D_role[] dRoles = result.roles.mD_roleList; // using deserializer
if (dRoles != null) {
for (D_role role : dRoles) {
Log.d(TAG, role.name);
}
}
}
Logcat of NG result:
--------------------
D/DBG: IT1
D/DBGdbg: Contacts unavailable
D/DBG: IT2
D/DBGdbg: Contacts unavailable
D/DBG: ADMIN
D/DBG: MANAGER
Logcat of OK result:
--------------------
D/DBG: IT1
D/DBGdbg: IT1 CCC11
D/DBGdbg: IT1 CCC12
D/DBG: IT2
D/DBGdbg: IT2 CCC21
D/DBG: ADMIN
D/DBG: MANAGER
Результаты:
Для целей анализа предоставленный исходный код имеет возможность включать / отключать использование десериализаторов с помощью комментариев / комментариев. Здесь NG означает «ничего хорошего», я не могу извлечь contact
содержимое.
Для этих комбинаций ниже мои результаты: NG:
Все dept
, role
, contact
десериализаторы активны.
Активны только dept
, contact
десериализаторы.
Для этих комбинации ниже, мои результаты в порядке:
Только десериализаторы role
, contact
активны, десериализатор dept
отключен.
Только десериализаторы role
, dept
активны, с contact
десериализатор отключен.
Анализ результатов:
5.1. Десериализатор contact
равен NG, если десериализатор dept
включен. См. (1), (2).
5.2. Десериализатор contact
работает, когда десериализатор dept
отключен. См. (3).
5.3. Несколько десериализаторов на одном уровне иерархии в порядке. См. (4).
Вопросы:
6.1. Почему содержимое contact
недоступно, если включен десериализатор dept
?
6.2. Какие модификации необходимы для работы всех трех десериализаторов?
Спасибо.
Решение:
Большое спасибо Гургену Гевондову за решение. Проблема заключается в неправильном размещении внутреннего десериализатора contact
. Найдите fixme
обновленный код. Добавили дополнительные тестовые случаи. Теперь можно анализировать dept
, contact
, являются ли они JsonArray или JsonObject.
public class D_depts {
// fixme: choose either (A) or (B)
// region - (A) not using deserializer
//
// public D_dept[] dept;
//
// endregion - (A) not using deserializer
// region - (B) using deserializer
private static final String TAG_dept = "dept";
public D_dept mD_dept;
public D_dept[] mD_deptList;
public void setD_dept(D_dept d_dept) {
mD_dept = d_dept;
}
public void setD_deptList(D_dept[] d_deptList) {
mD_deptList = d_deptList;
}
public static class D_deptsDeserializer implements JsonDeserializer<D_depts> {
@Override
public D_depts deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
D_depts depts = new Gson().fromJson(json, D_depts.class);
//fixme-add
Gson gson = new GsonBuilder()
.registerTypeAdapter(D_contacts.class, new D_contacts.D_contactsDeserializer())
.create();
JsonObject jsonObject = json.getAsJsonObject();
if (jsonObject.has(TAG_dept)) {
JsonElement jsonElement = jsonObject.get(TAG_dept);
if (jsonElement.isJsonArray()) {
JsonArray array = jsonElement.getAsJsonArray();
// D_dept[] values = new Gson().fromJson(array, D_dept[].class); //fixme:del
D_dept[] values = gson.fromJson(array, D_dept[].class); //fixme:add
depts.setD_deptList(values);
} else if (jsonElement.isJsonObject()) {
JsonObject object = jsonElement.getAsJsonObject();
// D_dept value = new Gson().fromJson(object, D_dept.class); //fixme:del
D_dept value = gson.fromJson(object, D_dept.class); //fixme:add
depts.setD_dept(value);
} else {
}
}
return depts;
}
}
// endregion - (B) using deserializer
}
private static String sJsonString1 = "{\"depts\":{\"dept\":[{\"name\":\"IT1\",\"contacts\":{\"contact\":[{\"name\":\"CCC11\"},{\"name\":\"CCC12\"}]}},{\"name\":\"IT2\",\"contacts\":{\"contact\":[{\"name\":\"CCC21\"}]}}]},\"roles\":{\"role\":[{\"name\":\"ADMIN\"},{\"name\":\"MANAGER\"}]}}";
private static String sJsonString2 = "{\"depts\":{\"dept\":[{\"name\":\"IT1\",\"contacts\":{\"contact\":[{\"name\":\"CCC11\"},{\"name\":\"CCC12\"}]}},{\"name\":\"IT2\",\"contacts\":{\"contact\":{\"name\":\"CCC21_obj\"}}}]},\"roles\":{\"role\":[{\"name\":\"ADMIN\"},{\"name\":\"MANAGER\"}]}}";
private static String sJsonString3 = "{\"depts\":{\"dept\":{\"name\":\"IT3_obj\",\"contacts\":{\"contact\":[{\"name\":\"CCC31\"},{\"name\":\"CCC32\"}]}}},\"roles\":{\"role\":[{\"name\":\"ADMIN\"},{\"name\":\"MANAGER\"}]}}";
private static String sJsonString4 = "{\"depts\":{\"dept\":{\"name\":\"IT4_obj\",\"contacts\":{\"contact\":{\"name\":\"CCC41_obj\"}}}},\"roles\":{\"role\":[{\"name\":\"ADMIN\"},{\"name\":\"MANAGER\"}]}}";
private static final String[] sJsonStrings = new String[] {
sJsonString1 // dept as array, contact as array
,sJsonString2 // dept as array, contact as object
,sJsonString3 // dept as object, contact as array
,sJsonString4 // dept as object, contact as object
};
private void vTests() {
for (String s : sJsonStrings) {
Log.d(TAG, "--------------------");
vTest(s);
}
Log.d(TAG, "--------------------");
}
private void vTest(String jsonString) {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(D_depts.class, new D_depts.D_deptsDeserializer());
gsonBuilder.registerTypeAdapter(D_roles.class, new D_roles.D_rolesDeserializer());
// gsonBuilder.registerTypeAdapter(D_contacts.class, new D_contacts.D_contactsDeserializer()); //fixme:del
Gson gson = gsonBuilder.create();
D_result result = gson.fromJson(jsonString, D_result.class);
if (result.depts.mD_deptList != null) {
for (D_dept dept : result.depts.mD_deptList) {
Log.d(TAG, dept.name);
vShowContacts(dept.contacts, dept);
}
} else if (result.depts.mD_dept != null) {
D_dept dept = result.depts.mD_dept;
Log.d(TAG, dept.name);
vShowContacts(dept.contacts, dept);
}
D_role[] dRoles = result.roles.mD_roleList;
if (dRoles != null) {
for (D_role role : dRoles) {
Log.d(TAG, role.name);
}
}
}
private void vShowContacts(D_contacts contacts, D_dept dept) {
if (contacts.mD_contactList != null) {
for (D_contact contact : contacts.mD_contactList) {
Log.d(TAG+"dbgL", dept.name + " " + contact.name);
}
} else if (contacts.mD_contact != null) {
D_contact contact = contacts.mD_contact;
Log.d(TAG+"dbg1", dept.name + " " + contact.name);
}
}