如何使用 Moshi 将不同的对象属性反序列化为一个共同的 class?

How to deserialize different object properties into a common class with Moshi?

我开始编写 Java 库 Brockman to parse a JSON response similar to this example using Moshi。但是,格式需要对 stream 个对象进行一些概括。

视频流摘录:

{
    "slug": "hd-native",
    "display": "Saal 1 FullHD Video",
    "type": "video",
    "isTranslated": false,
    "videoSize": [
        1920,
        1080
    ],
    "urls": {
        "webm": {
            "display": "WebM",
            "tech": "1920x1080, VP8+Vorbis in WebM, 2.8 MBit/s",
            "url": "http://example.com/s1_native_hd.webm"
        },
        "hls": {
            "display": "HLS",
            "tech": "1920x1080, h264+AAC im MPEG-TS-Container via HTTP",
            "url": "http://example.com/hls/s1_native_hd.m3u8"
        }
    }
}

音频流摘录:

{
    "slug": "audio-native",
    "display": "Saal 1 Audio",
    "type": "audio",
    "isTranslated": false,
    "videoSize": null,
    "urls": {
        "mp3": {
            "display": "MP3",
            "tech": "MP3-Audio, 96 kBit/s",
            "url": "http://example.com/s1_native.mp3"
        },
        "opus": {
            "display": "Opus",
            "tech": "Opus-Audio, 64 kBit/s",
            "url": "http://example.com/s1_native.opus"
        }
    }
}

urls = {} 对象的内容根据 stream typevideo 还是 audio 而不同,如上例所示.

目前只有Mp3 and Opus两个属性相同的模型。我想用 Format class 代替它们,它也可以作为缺少的 WebmHls class 的替代品。我怎样才能真正将 Urls 对象的不同字段映射到 Format class?

public class Format {

    public final String display;
    public final String tech;
    public final String url;

    public Format(String display, String tech, String url) {
        this.display = display;
        this.tech = tech;
        this.url = url;
    }
}

我可以想象 Stream class 看起来像这样:

public class Stream {

    public final String display;
    public final boolean isTranslated;
    public final String slug;
    public final String type;
    public final VideoSize videoSize;
    public final List<Format> urls; // How to map into List<Format>?

// ...

我得出以下结论:

public class StreamAdapter {

    @ToJson
    public String toJson(Stream stream) throws Exception {
        throw new UnsupportedOperationException("Not yet implemented.");
    }

    @FromJson
    public Stream fromJson(StreamJson streamJson) throws Exception {
        String slug = streamJson.slug;
        String display = streamJson.display;
        boolean isTranslated = streamJson.isTranslated;
        Stream.TYPE type = streamJson.type;
        VideoSize videoSize = streamJson.videoSize;
        Map<String, Object> urlsJson = streamJson.urls;
        List<Url> urls = getUrls(urlsJson);
        return new Stream(display, isTranslated, slug, type, videoSize, urls);
    }

    private List<Url> getUrls(Map<String, Object> urlsJson) {
        Set<String> urlTypes = urlsJson.keySet();
        List<Url> urls = new ArrayList<Url>(urlTypes.size());
        for (String urlType : urlTypes) {
            @SuppressWarnings("unchecked")
            Map<String, String> urlProperties = (Map<String, String>) urlsJson.get(urlType);
            urls.add(getUrl(urlType, urlProperties));
        }
        return urls;
    }

    private Url getUrl(String urlType, Map<String, String> properties) {
        Url.TYPE type = new UrlTypeAdapter().fromJson(urlType);
        String display = properties.get("display");
        String tech = properties.get("tech");
        String url = properties.get("url");
        return new Url(type, display, tech, url);
    }

    private static final class StreamJson {
        String slug;
        String display;
        boolean isTranslated;
        Stream.TYPE type;
        VideoSize videoSize;
        Map<String, Object> urls;
    }

}

请注意,我现在使用 Url class 而不是问题中提到的 Format class。请查找更多详细信息 here。如果您有关于如何改进这一点的想法,欢迎您在此处发表评论在存储库上创建一个issue/pull请求