当前位置: 首页 > 知识库问答 >
问题:

retrofit2中嵌套json数组(多类型对象)的JsonDeserializer

冀胤运
2023-03-14

我的json响应

[
     [
        {
          "header_id": 1,
          "name" : "Tom",
          "group" : "A"
        },
        {
          "header_id": 2,
          "name" : "Marry",
          "group" : "B"
         }
    ],

    [
         {
             "object_id" : 1,
             "SerialNo" : 123456
         },
         {
             "object_id" : 2,
             "SerialNo" : 89545
         }
     ],

     [
        {
           "workflow_id" : 1,
           "StatusName" : "start"
         },
         {
            "workflow_id" : 2,
            "StatusName" : "end"
          }

    ]
]
public class Header{
    @SerializedName("header_id")
    private int HeaderID;
    @SerializedName("name")
    private String name;
    @SerializedName("group")
    private String group;
}
public class ObjectWork {
    @SerializedName("object_id")
    private int ObjectID;
    @SerializedName("SerialNo")
    private int SerialNo;
}
public class WorkFlow{
    @SerializedName("workflow_id")
    private int WorkflowID;
    @SerializedName("StatusName")
     private String statusName;
}

谢谢

共有1个答案

霍永年
2023-03-14

引入一个通用包装器来让Gson识别您的自Gson禁止java.lang.object重写(注意推荐的fieldNamesCaseThatIsAlwaysCamelCase):

abstract class AbstractCommon {
}
final class Header
        extends AbstractCommon {

    @SerializedName("header_id")
    final int headerId = Integer.valueOf(0);

    @SerializedName("name")
    final String name = null;

    @SerializedName("group")
    final String group = null;

    @Override
    public String toString() {
        return headerId + ": " + name;
    }

}
final class ObjectWork
        extends AbstractCommon {

    @SerializedName("object_id")
    final int objectId = Integer.valueOf(0);

    @SerializedName("SerialNo")
    final int serialNo = Integer.valueOf(0);

    @Override
    public String toString() {
        return objectId + ": " + serialNo;
    }

}
final class WorkFlow
        extends AbstractCommon {

    @SerializedName("workflow_id")
    final int workflowId = Integer.valueOf(0);

    @SerializedName("StatusName")
    final String statusName = null;

    @Override
    public String toString() {
        return workflowId + ": " + statusName;
    }

}

现在引入一个JSONDeserializer,它将尝试识别实际类型:

private static final Gson gson = new GsonBuilder()
        .registerTypeAdapter(AbstractCommon.class, (JsonDeserializer<AbstractCommon>) (jsonElement, type, context) -> {
            final JsonObject jsonObject = jsonElement.getAsJsonObject();
            if ( jsonObject.has("header_id") ) {
                return context.deserialize(jsonElement, Header.class);
            }
            if ( jsonObject.has("object_id") ) {
                return context.deserialize(jsonElement, ObjectWork.class);
            }
            if ( jsonObject.has("workflow_id") ) {
                return context.deserialize(jsonElement, WorkFlow.class);
            }
            throw new IllegalArgumentException("Cannot recognize: " + jsonElement);
        })
        .create();

现在您可以轻松地做到:

private static final Type commonsType = new TypeToken<List<List<AbstractCommon>>>() {
}.getType();

public static void main(final String... args)
        throws IOException {
    try ( final JsonReader jsonReader = getPackageResourceJsonReader(Q44034331.class, "arrays.json") ) {
        final List<List<AbstractCommon>> commons = gson.fromJson(jsonReader, commonsType);
        commons.stream()
                .flatMap(Collection::stream)
                .forEach(abstractCommon -> System.out.println(abstractCommon.getClass().getSimpleName() + ": " + abstractCommon));
    }
}
final class Wrapper {

    final Header header;
    final ObjectWork objectWork;
    final WorkFlow workFlow;

    Wrapper(final Header header, final ObjectWork objectWork, final WorkFlow workFlow) {
        this.header = header;
        this.objectWork = objectWork;
        this.workFlow = workFlow;
    }

}
private static Collection<Wrapper> combine(final List<List<AbstractCommon>> commons) {
    @SuppressWarnings({ "unchecked", "rawtypes" })
    final List<Header> headers = (List) commons.get(0);
    @SuppressWarnings({ "unchecked", "rawtypes" })
    final List<ObjectWork> objectWorks = (List) commons.get(1);
    @SuppressWarnings({ "unchecked", "rawtypes" })
    final List<WorkFlow> workFlows = (List) commons.get(2);
    final Iterator<Header> headerIterator = headers.iterator();
    final Iterator<ObjectWork> objectWorkIterator = objectWorks.iterator();
    final Iterator<WorkFlow> workFlowIterator = workFlows.iterator();
    final Collection<Wrapper> wrappers = new ArrayList<>();
    while ( headerIterator.hasNext() && objectWorkIterator.hasNext() && workFlowIterator.hasNext() ) {
        final Header header = headerIterator.next();
        final ObjectWork objectWork = objectWorkIterator.next();
        final WorkFlow workFlow = workFlowIterator.next();
        final Wrapper wrapper = new Wrapper(header, objectWork, workFlow);
        wrappers.add(wrapper);
    }
    return wrappers;
}
combine(commons)
        .forEach(wrapper -> System.out.println(wrapper.header + ", " + wrapper.objectWork + ", " + wrapper.workFlow));

产出:

1:Tom,1:123456,1:Start
2:Marrid,2:89545,2:end

 类似资料:
  • 问题内容: 我必须遍历json数组对象。 它具有以下结构。 基本上我在做的是prod_1是产品的名称,并且prod_1的版本列表已填充在其中。 所以现在我想要的是产品的名称以及它的版本。 问题在于可能有很多产品和该产品下的许多版本。所以我需要可以在 javascript 中使用适当的循环结构来对其进行处理。 最好将循环将产品名称存储在一个变量中,将版本存储在另一个变量中,因为我需要对产品名称进行一

  • 问题内容: 有一个小问题上的话题,但他们都不来覆盖我的情况,因此我创建一个新的。 我有如下的JSON: 有没有办法解组嵌套的bar属性并将其直接分配给struct属性而不创建嵌套的struct? 我现在采用的解决方案如下: 这是简化版本,请忽略详细信息。如您所见,我希望能够解析并将其值分配给 我见过有人在使用地图,但这不是我的情况。除了一些特定的元素外,我基本上不关心(一个大对象)的内容。 在这种

  • 我只想扁平化嵌套JSON的属性,但仍然适用于输入数组中的所有对象 很难将这三个字段放在一个规范中(类型字段、geo字段、properties字段)。我编写了规范来单独完成每一个操作,但是当我将这些规范组合在一个对象中使用时,它会产生错误的输出--对象数组真的把它搞砸了。 期望输出:

  • 我正在使用空手道JavaAPI处理Json对象。我将创建以下json: 当我尝试,我得到以下错误: json路径语法经过交叉检查是正确的,我可能缺少的任何其他点? 编辑:我正在使用v1。空手道核心1.0

  • 问题内容: 我对mongodb还是很陌生,有一件事我现在无法解决: 假设您有以下文档(简体): 哪个查询将返回json-object,其值等于“ value2”? 这意味着,我需要这个json-object: 当然,我已经尝试了很多可能的查询,但是没有一个返回正确的查询,例如 有人可以帮我看看我在做什么错吗? 谢谢! 问题答案: 使用位置运算符 输出量 使用聚合 输出 使用Java驱动程序 输出

  • 我有一个带有嵌套字段的JSON: 我正在使用JSONPATH从嵌套中获取。 我已经将我的JSON文本粘贴到了http://jsonpath.com/这个网站上;并且在使用了这一行之后: 我得到了这个: 使用此行后: 我得到了这个: 我尝试返回(输出)的内容如下: 但是我找不到合适的语法来将这两个组合在一行中,并用一个JSONPATH查询返回它们。