quicktype icon indicating copy to clipboard operation
quicktype copied to clipboard

fix dart null-safety

Open RmondJone opened this issue 3 years ago • 3 comments

1、适配Dart空安全代码生成不对的问题 2、删除Dart生成冗余代码 3、修改Dart字段注释不对的问题 4、适配required-props属性生成代码@required不对的问题

1、The problem of incorrect generation of Dart empty security code 2、 Delete Dart to generate redundant code 3、Modify the problem of incorrect Dart field annotations 4、The problem of adapting the required-props property to generate code @required is incorrect

// To parse this JSON data, do
//
//     final test = testFromJson(jsonString);

import 'dart:convert';

Test? testFromJson(String str) => Test.fromJson(json.decode(str));

String testToJson(Test? data) => json.encode(data!.toJson());

class Test {
    Test({
        this.code,
        this.info,
        this.msg,
        this.traceId,
    });

    
    ///响应码
    double? code;
    
    ///结果数据
    Info? info;
    String? msg;
    String? traceId;

    factory Test.fromJson(Map<String, dynamic> json) => Test(
        code: json["code"].toDouble(),
        info: json["info"],
        msg: json["msg"],
        traceId: json["traceId"],
    );

    Map<String, dynamic> toJson() => {
        "code": code,
        "info": info,
        "msg": msg,
        "traceId": traceId,
    };
}


///结果数据
class Info {
    Info({
        this.baseDetail,
        this.contractActivityInfos,
        this.productActivityInfos,
        this.productParam,
        this.serviceInfo,
        this.shoppingActivityInfos,
    });

    
    ///商品详情页基础详情(图片、视频、展示价格、普通价、名称、描述、是否收藏、是否在活动)
    BaseDetail? baseDetail;
    
    ///合约通详情
    List<ContractActivityInfo?>? contractActivityInfos;
    
    ///商品参与的活动的信息,仅商品参与了活动时有值
    List<ProductActivityInfo?>? productActivityInfos;
    
    ///产品参数
    ProductParam? productParam;
    
    ///商品服务信息
    ServiceInfo? serviceInfo;
    
    ///加购浮层、购物车切换活动的活动信息列表
    List<ShoppingActivityInfo?>? shoppingActivityInfos;

    factory Info.fromJson(Map<String, dynamic> json) => Info(
        baseDetail: json["baseDetail"],
        contractActivityInfos: json["contractActivityInfos"] == null ? [] : List<ContractActivityInfo?>.from(json["contractActivityInfos"]!.map((x) => ContractActivityInfo.fromJson(x))),
        productActivityInfos: json["productActivityInfos"] == null ? [] : List<ProductActivityInfo?>.from(json["productActivityInfos"]!.map((x) => ProductActivityInfo.fromJson(x))),
        productParam: json["productParam"],
        serviceInfo: json["serviceInfo"],
        shoppingActivityInfos: json["shoppingActivityInfos"] == null ? [] : List<ShoppingActivityInfo?>.from(json["shoppingActivityInfos"]!.map((x) => ShoppingActivityInfo.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "baseDetail": baseDetail,
        "contractActivityInfos": contractActivityInfos == null ? [] : List<dynamic>.from(contractActivityInfos!.map((x) => x!.toJson())),
        "productActivityInfos": productActivityInfos == null ? [] : List<dynamic>.from(productActivityInfos!.map((x) => x!.toJson())),
        "productParam": productParam,
        "serviceInfo": serviceInfo,
        "shoppingActivityInfos": shoppingActivityInfos == null ? [] : List<dynamic>.from(shoppingActivityInfos!.map((x) => x!.toJson())),
    };
}


///商品详情页基础详情(图片、视频、展示价格、普通价、名称、描述、是否收藏、是否在活动)
class BaseDetail {
    BaseDetail({
        this.beSmallGood,
        this.caption,
        this.haveStock,
        this.images,
        this.isCollectionItem,
        this.isInActivity,
        this.isRestrictSale,
        this.itemFlag,
        this.itemId,
        this.itemName,
        this.itemPoint,
        this.itemStockDescribe,
        this.normalPrice,
        this.saleCount,
        this.salePrice,
        this.saleUnit,
        this.shortVideo,
        this.showMobilLabel,
        this.showPrice,
        this.skuRoList,
        this.stockList,
        this.supplierCode,
        this.tags,
        this.videoCover,
        this.warehouseInfos,
    });

    
    ///是否为小商品
    bool? beSmallGood;
    
    ///商品详情页的副标题描述
    String? caption;
    
    ///商品是否有销售库存(实物库存)
    bool? haveStock;
    
    ///商品详情页图片列表
    List<Image?>? images;
    
    ///是否已经加入收藏
    bool? isCollectionItem;
    
    ///是否是活动商品
    bool? isInActivity;
    
    ///是否限售
    bool? isRestrictSale;
    
    ///自营厂送标签
    String? itemFlag;
    
    ///商品id
    int? itemId;
    
    ///商品名称
    String? itemName;
    
    ///商品积分数
    int? itemPoint;
    
    ///商品库存描述
    String? itemStockDescribe;
    
    ///商品详情页展示的普通价格,优先透出区域价再透出全国价
    String? normalPrice;
    
    ///编码数量
    int? saleCount;
    
    ///价格(含¥符号),如果限售,此字段返回“指定客户专享
    String? salePrice;
    
    ///商品销售单位
    String? saleUnit;
    
    ///短视频地址
    String? shortVideo;
    
    ///美孚客户分组
    String? showMobilLabel;
    
    ///商品列表页和详情页展示的价格,若为普通商品优先透出区域价再透出全国价;若为活动商品透出各活动中的最低价
    String? showPrice;
    
    ///SKU
    List<SkuRoList?>? skuRoList;
    
    ///库存信息
    List<String?>? stockList;
    
    ///供应商编码
    String? supplierCode;
    
    ///商品标签文案(厂家直发,辅材仓直发)
    List<String?>? tags;
    
    ///短视频封面图
    String? videoCover;
    
    ///仓库信息列表
    List<WarehouseInfo?>? warehouseInfos;

    factory BaseDetail.fromJson(Map<String, dynamic> json) => BaseDetail(
        beSmallGood: json["beSmallGood"],
        caption: json["caption"],
        haveStock: json["haveStock"],
        images: json["images"] == null ? [] : List<Image?>.from(json["images"]!.map((x) => Image.fromJson(x))),
        isCollectionItem: json["isCollectionItem"],
        isInActivity: json["isInActivity"],
        isRestrictSale: json["isRestrictSale"],
        itemFlag: json["itemFlag"],
        itemId: json["itemId"],
        itemName: json["itemName"],
        itemPoint: json["itemPoint"],
        itemStockDescribe: json["itemStockDescribe"],
        normalPrice: json["normalPrice"],
        saleCount: json["saleCount"],
        salePrice: json["salePrice"],
        saleUnit: json["saleUnit"],
        shortVideo: json["shortVideo"],
        showMobilLabel: json["showMobilLabel"],
        showPrice: json["showPrice"],
        skuRoList: json["skuROList"] == null ? [] : List<SkuRoList?>.from(json["skuROList"]!.map((x) => SkuRoList.fromJson(x))),
        stockList: json["stockList"] == null ? [] : List<String?>.from(json["stockList"]!.map((x) => x)),
        supplierCode: json["supplierCode"],
        tags: json["tags"] == null ? [] : List<String?>.from(json["tags"]!.map((x) => x)),
        videoCover: json["videoCover"],
        warehouseInfos: json["warehouseInfos"] == null ? [] : List<WarehouseInfo?>.from(json["warehouseInfos"]!.map((x) => WarehouseInfo.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "beSmallGood": beSmallGood,
        "caption": caption,
        "haveStock": haveStock,
        "images": images == null ? [] : List<dynamic>.from(images!.map((x) => x!.toJson())),
        "isCollectionItem": isCollectionItem,
        "isInActivity": isInActivity,
        "isRestrictSale": isRestrictSale,
        "itemFlag": itemFlag,
        "itemId": itemId,
        "itemName": itemName,
        "itemPoint": itemPoint,
        "itemStockDescribe": itemStockDescribe,
        "normalPrice": normalPrice,
        "saleCount": saleCount,
        "salePrice": salePrice,
        "saleUnit": saleUnit,
        "shortVideo": shortVideo,
        "showMobilLabel": showMobilLabel,
        "showPrice": showPrice,
        "skuROList": skuRoList == null ? [] : List<dynamic>.from(skuRoList!.map((x) => x!.toJson())),
        "stockList": stockList == null ? [] : List<dynamic>.from(stockList!.map((x) => x)),
        "supplierCode": supplierCode,
        "tags": tags == null ? [] : List<dynamic>.from(tags!.map((x) => x)),
        "videoCover": videoCover,
        "warehouseInfos": warehouseInfos == null ? [] : List<dynamic>.from(warehouseInfos!.map((x) => x!.toJson())),
    };
}

class Image {
    Image({
        this.imgOrder,
        this.isMasterImage,
        this.itemImageId,
        this.large,
        this.medium,
        this.original,
        this.thumbnail,
    });

    
    ///商品图片顺序
    int? imgOrder;
    
    ///是否为商品主图
    bool? isMasterImage;
    
    ///商品图片id
    int? itemImageId;
    
    ///大图
    String? large;
    
    ///中图
    String? medium;
    
    ///原图
    String? original;
    
    ///小图
    String? thumbnail;

    factory Image.fromJson(Map<String, dynamic> json) => Image(
        imgOrder: json["imgOrder"],
        isMasterImage: json["isMasterImage"],
        itemImageId: json["itemImageId"],
        large: json["large"],
        medium: json["medium"],
        original: json["original"],
        thumbnail: json["thumbnail"],
    );

    Map<String, dynamic> toJson() => {
        "imgOrder": imgOrder,
        "isMasterImage": isMasterImage,
        "itemImageId": itemImageId,
        "large": large,
        "medium": medium,
        "original": original,
        "thumbnail": thumbnail,
    };
}

class SkuRoList {
    SkuRoList({
        this.kzSkuCode,
    });

    
    ///编码
    String? kzSkuCode;

    factory SkuRoList.fromJson(Map<String, dynamic> json) => SkuRoList(
        kzSkuCode: json["kzSkuCode"],
    );

    Map<String, dynamic> toJson() => {
        "kzSkuCode": kzSkuCode,
    };
}

class WarehouseInfo {
    WarehouseInfo({
        this.cityName,
        this.provinceName,
        this.region,
        this.stock,
        this.warehouseCode,
        this.warehouseEffective,
        this.warehouseName,
    });

    
    ///仓库所在的市
    String? cityName;
    
    ///仓库所在的省份
    String? provinceName;
    
    ///所在地区
    String? region;
    
    ///库存10个以下显示个数,否则只显示充足
    String? stock;
    
    ///仓库编码
    String? warehouseCode;
    
    ///仓库时效
    String? warehouseEffective;
    
    ///仓库名
    String? warehouseName;

    factory WarehouseInfo.fromJson(Map<String, dynamic> json) => WarehouseInfo(
        cityName: json["cityName"],
        provinceName: json["provinceName"],
        region: json["region"],
        stock: json["stock"],
        warehouseCode: json["warehouseCode"],
        warehouseEffective: json["warehouseEffective"],
        warehouseName: json["warehouseName"],
    );

    Map<String, dynamic> toJson() => {
        "cityName": cityName,
        "provinceName": provinceName,
        "region": region,
        "stock": stock,
        "warehouseCode": warehouseCode,
        "warehouseEffective": warehouseEffective,
        "warehouseName": warehouseName,
    };
}

class ContractActivityInfo {
    ContractActivityInfo({
        this.activityDesc,
        this.activityId,
        this.activityInfoFull,
        this.activityInfoFullText,
        this.activityName,
        this.activityStep,
        this.activityStepInfos,
        this.activityTags,
        this.activityTypeId,
        this.activityTypeName,
        this.activityTypeTag,
        this.activityUrl,
        this.activityUrlNew,
        this.giftOverlayDescription,
        this.haveStock,
        this.isRefundCoupon,
        this.limitNum,
        this.miniBuyNum,
        this.priceDesc,
        this.refundCouponInfo,
    });

    
    ///合约通描述
    String? activityDesc;
    
    ///活动id
    double? activityId;
    
    ///商品参与活动信息的各个阶梯主信息拼接(如:购满1送1赠品;购满2送2赠品;)
    String? activityInfoFull;
    
    ///商品参与活动主信息不含富文本
    String? activityInfoFullText;
    
    ///合约通名称
    String? activityName;
    
    ///活动阶段1未开始2进行中
    int? activityStep;
    
    ///活动各阶梯的信息
    List<ContractActivityInfoActivityStepInfo?>? activityStepInfos;
    
    ///活动的标签集合(如:满赠、返券)P264前在板块里和浮层里都用到,P264后只在板块用到
    List<ContractActivityInfoActivityTag?>? activityTags;
    
    ///
    ///活动类型的id1:每满赠;2:阶梯满赠;3:买本品赠本品;@com.qccr.bmarketcenter.facade.constant.GiftPromotionConstantsP243前在浮层用到
    int? activityTypeId;
    
    ///活动类型的名称
    String? activityTypeName;
    
    ///活动类型标签P264后新增,在浮层中用到
    ContractActivityInfoActivityTypeTag? activityTypeTag;
    
    ///活动H5页面地址
    String? activityUrl;
    
    ///活动页面地址,可能为scheml或h5
    String? activityUrlNew;
    
    ///赠品是否可叠加文案描述不可叠加:达成累计条件,以下赠品可任选一档获取,不可叠加可叠加:达成累计条件,以下赠品可叠加获取
    String? giftOverlayDescription;
    
    ///商品在活动中是否还有库存(实物库存虚拟库存、总限购)
    bool? haveStock;
    
    ///true为有返券P264前在浮层用到
    bool? isRefundCoupon;
    
    ///限购数
    int? limitNum;
    
    ///起购数
    int? miniBuyNum;
    
    ///商品在活动里的价格
    String? priceDesc;
    
    ///返券信息,isRefundCoupon为true时有值P264前在浮层用到
    String? refundCouponInfo;

    factory ContractActivityInfo.fromJson(Map<String, dynamic> json) => ContractActivityInfo(
        activityDesc: json["activityDesc"],
        activityId: json["activityId"],
        activityInfoFull: json["activityInfoFull"],
        activityInfoFullText: json["activityInfoFullText"],
        activityName: json["activityName"],
        activityStep: json["activityStep"],
        activityStepInfos: json["activityStepInfos"] == null ? [] : List<ContractActivityInfoActivityStepInfo?>.from(json["activityStepInfos"]!.map((x) => ContractActivityInfoActivityStepInfo.fromJson(x))),
        activityTags: json["activityTags"] == null ? [] : List<ContractActivityInfoActivityTag?>.from(json["activityTags"]!.map((x) => ContractActivityInfoActivityTag.fromJson(x))),
        activityTypeId: json["activityTypeId"],
        activityTypeName: json["activityTypeName"],
        activityTypeTag: json["activityTypeTag"],
        activityUrl: json["activityUrl"],
        activityUrlNew: json["activityUrlNew"],
        giftOverlayDescription: json["giftOverlayDescription"],
        haveStock: json["haveStock"],
        isRefundCoupon: json["isRefundCoupon"],
        limitNum: json["limitNum"],
        miniBuyNum: json["miniBuyNum"],
        priceDesc: json["priceDesc"],
        refundCouponInfo: json["refundCouponInfo"],
    );

    Map<String, dynamic> toJson() => {
        "activityDesc": activityDesc,
        "activityId": activityId,
        "activityInfoFull": activityInfoFull,
        "activityInfoFullText": activityInfoFullText,
        "activityName": activityName,
        "activityStep": activityStep,
        "activityStepInfos": activityStepInfos == null ? [] : List<dynamic>.from(activityStepInfos!.map((x) => x!.toJson())),
        "activityTags": activityTags == null ? [] : List<dynamic>.from(activityTags!.map((x) => x!.toJson())),
        "activityTypeId": activityTypeId,
        "activityTypeName": activityTypeName,
        "activityTypeTag": activityTypeTag,
        "activityUrl": activityUrl,
        "activityUrlNew": activityUrlNew,
        "giftOverlayDescription": giftOverlayDescription,
        "haveStock": haveStock,
        "isRefundCoupon": isRefundCoupon,
        "limitNum": limitNum,
        "miniBuyNum": miniBuyNum,
        "priceDesc": priceDesc,
        "refundCouponInfo": refundCouponInfo,
    };
}

class ContractActivityInfoActivityStepInfo {
    ContractActivityInfoActivityStepInfo({
        this.activityExtInfo,
        this.activityExtTag,
        this.activityInfo,
        this.isHasExtInfo,
        this.isHasExtTag,
        this.isHasInfo,
    });

    
    ///无
    String? activityExtInfo;
    
    ///无
    PurpleActivityExtTag? activityExtTag;
    
    ///无
    String? activityInfo;
    
    ///无
    bool? isHasExtInfo;
    
    ///无
    bool? isHasExtTag;
    
    ///无
    bool? isHasInfo;

    factory ContractActivityInfoActivityStepInfo.fromJson(Map<String, dynamic> json) => ContractActivityInfoActivityStepInfo(
        activityExtInfo: json["activityExtInfo"],
        activityExtTag: json["activityExtTag"],
        activityInfo: json["activityInfo"],
        isHasExtInfo: json["isHasExtInfo"],
        isHasExtTag: json["isHasExtTag"],
        isHasInfo: json["isHasInfo"],
    );

    Map<String, dynamic> toJson() => {
        "activityExtInfo": activityExtInfo,
        "activityExtTag": activityExtTag,
        "activityInfo": activityInfo,
        "isHasExtInfo": isHasExtInfo,
        "isHasExtTag": isHasExtTag,
        "isHasInfo": isHasInfo,
    };
}


///无
class PurpleActivityExtTag {
    PurpleActivityExtTag({
        this.borderColor,
        this.fontColor,
        this.shadingColor,
        this.tagText,
    });

    
    ///无
    String? borderColor;
    
    ///无
    String? fontColor;
    
    ///无
    String? shadingColor;
    
    ///无
    String? tagText;

    factory PurpleActivityExtTag.fromJson(Map<String, dynamic> json) => PurpleActivityExtTag(
        borderColor: json["borderColor"],
        fontColor: json["fontColor"],
        shadingColor: json["shadingColor"],
        tagText: json["tagText"],
    );

    Map<String, dynamic> toJson() => {
        "borderColor": borderColor,
        "fontColor": fontColor,
        "shadingColor": shadingColor,
        "tagText": tagText,
    };
}

class ContractActivityInfoActivityTag {
    ContractActivityInfoActivityTag({
        this.borderColor,
        this.fontColor,
        this.shadingColor,
        this.tagText,
    });

    
    ///无
    String? borderColor;
    
    ///无
    String? fontColor;
    
    ///无
    String? shadingColor;
    
    ///无
    String? tagText;

    factory ContractActivityInfoActivityTag.fromJson(Map<String, dynamic> json) => ContractActivityInfoActivityTag(
        borderColor: json["borderColor"],
        fontColor: json["fontColor"],
        shadingColor: json["shadingColor"],
        tagText: json["tagText"],
    );

    Map<String, dynamic> toJson() => {
        "borderColor": borderColor,
        "fontColor": fontColor,
        "shadingColor": shadingColor,
        "tagText": tagText,
    };
}


///活动类型标签P264后新增,在浮层中用到
class ContractActivityInfoActivityTypeTag {
    ContractActivityInfoActivityTypeTag({
        this.borderColor,
        this.fontColor,
        this.shadingColor,
        this.tagText,
    });

    
    ///无
    String? borderColor;
    
    ///无
    String? fontColor;
    
    ///无
    String? shadingColor;
    
    ///无
    String? tagText;

    factory ContractActivityInfoActivityTypeTag.fromJson(Map<String, dynamic> json) => ContractActivityInfoActivityTypeTag(
        borderColor: json["borderColor"],
        fontColor: json["fontColor"],
        shadingColor: json["shadingColor"],
        tagText: json["tagText"],
    );

    Map<String, dynamic> toJson() => {
        "borderColor": borderColor,
        "fontColor": fontColor,
        "shadingColor": shadingColor,
        "tagText": tagText,
    };
}

class ProductActivityInfo {
    ProductActivityInfo({
        this.activityDesc,
        this.activityId,
        this.activityInfoFull,
        this.activityInfoFullText,
        this.activityName,
        this.activityStep,
        this.activityStepInfos,
        this.activityTags,
        this.activityTypeId,
        this.activityTypeName,
        this.activityTypeTag,
        this.activityUrl,
        this.activityUrlNew,
        this.giftOverlayDescription,
        this.haveStock,
        this.isRefundCoupon,
        this.limitNum,
        this.miniBuyNum,
        this.priceDesc,
        this.refundCouponInfo,
    });

    
    ///合约通描述
    String? activityDesc;
    
    ///活动id
    double? activityId;
    
    ///商品参与活动信息的各个阶梯主信息拼接(如:购满1送1赠品;购满2送2赠品;)
    String? activityInfoFull;
    
    ///商品参与活动主信息不含富文本
    String? activityInfoFullText;
    
    ///合约通名称
    String? activityName;
    
    ///活动阶段1未开始2进行中
    int? activityStep;
    
    ///活动各阶梯的信息
    List<ProductActivityInfoActivityStepInfo?>? activityStepInfos;
    
    ///活动的标签集合(如:满赠、返券)P264前在板块里和浮层里都用到,P264后只在板块用到
    List<ProductActivityInfoActivityTag?>? activityTags;
    
    ///
    ///活动类型的id1:每满赠;2:阶梯满赠;3:买本品赠本品;@com.qccr.bmarketcenter.facade.constant.GiftPromotionConstantsP243前在浮层用到
    int? activityTypeId;
    
    ///活动类型的名称
    String? activityTypeName;
    
    ///活动类型标签P264后新增,在浮层中用到
    ProductActivityInfoActivityTypeTag? activityTypeTag;
    
    ///活动H5页面地址
    String? activityUrl;
    
    ///活动页面地址,可能为scheml或h5
    String? activityUrlNew;
    
    ///赠品是否可叠加文案描述不可叠加:达成累计条件,以下赠品可任选一档获取,不可叠加可叠加:达成累计条件,以下赠品可叠加获取
    String? giftOverlayDescription;
    
    ///商品在活动中是否还有库存(实物库存虚拟库存、总限购)
    bool? haveStock;
    
    ///true为有返券P264前在浮层用到
    bool? isRefundCoupon;
    
    ///限购数
    int? limitNum;
    
    ///起购数
    int? miniBuyNum;
    
    ///商品在活动里的价格
    String? priceDesc;
    
    ///返券信息,isRefundCoupon为true时有值P264前在浮层用到
    String? refundCouponInfo;

    factory ProductActivityInfo.fromJson(Map<String, dynamic> json) => ProductActivityInfo(
        activityDesc: json["activityDesc"],
        activityId: json["activityId"],
        activityInfoFull: json["activityInfoFull"],
        activityInfoFullText: json["activityInfoFullText"],
        activityName: json["activityName"],
        activityStep: json["activityStep"],
        activityStepInfos: json["activityStepInfos"] == null ? [] : List<ProductActivityInfoActivityStepInfo?>.from(json["activityStepInfos"]!.map((x) => ProductActivityInfoActivityStepInfo.fromJson(x))),
        activityTags: json["activityTags"] == null ? [] : List<ProductActivityInfoActivityTag?>.from(json["activityTags"]!.map((x) => ProductActivityInfoActivityTag.fromJson(x))),
        activityTypeId: json["activityTypeId"],
        activityTypeName: json["activityTypeName"],
        activityTypeTag: json["activityTypeTag"],
        activityUrl: json["activityUrl"],
        activityUrlNew: json["activityUrlNew"],
        giftOverlayDescription: json["giftOverlayDescription"],
        haveStock: json["haveStock"],
        isRefundCoupon: json["isRefundCoupon"],
        limitNum: json["limitNum"],
        miniBuyNum: json["miniBuyNum"],
        priceDesc: json["priceDesc"],
        refundCouponInfo: json["refundCouponInfo"],
    );

    Map<String, dynamic> toJson() => {
        "activityDesc": activityDesc,
        "activityId": activityId,
        "activityInfoFull": activityInfoFull,
        "activityInfoFullText": activityInfoFullText,
        "activityName": activityName,
        "activityStep": activityStep,
        "activityStepInfos": activityStepInfos == null ? [] : List<dynamic>.from(activityStepInfos!.map((x) => x!.toJson())),
        "activityTags": activityTags == null ? [] : List<dynamic>.from(activityTags!.map((x) => x!.toJson())),
        "activityTypeId": activityTypeId,
        "activityTypeName": activityTypeName,
        "activityTypeTag": activityTypeTag,
        "activityUrl": activityUrl,
        "activityUrlNew": activityUrlNew,
        "giftOverlayDescription": giftOverlayDescription,
        "haveStock": haveStock,
        "isRefundCoupon": isRefundCoupon,
        "limitNum": limitNum,
        "miniBuyNum": miniBuyNum,
        "priceDesc": priceDesc,
        "refundCouponInfo": refundCouponInfo,
    };
}

class ProductActivityInfoActivityStepInfo {
    ProductActivityInfoActivityStepInfo({
        this.activityExtInfo,
        this.activityExtTag,
        this.activityInfo,
        this.isHasExtInfo,
        this.isHasExtTag,
        this.isHasInfo,
    });

    
    ///额外信息
    String? activityExtInfo;
    
    ///额外标签
    FluffyActivityExtTag? activityExtTag;
    
    ///主要信息
    String? activityInfo;
    
    ///是否有额外信息
    bool? isHasExtInfo;
    
    ///是否有额外标签
    bool? isHasExtTag;
    
    ///是否有主要信息
    bool? isHasInfo;

    factory ProductActivityInfoActivityStepInfo.fromJson(Map<String, dynamic> json) => ProductActivityInfoActivityStepInfo(
        activityExtInfo: json["activityExtInfo"],
        activityExtTag: json["activityExtTag"],
        activityInfo: json["activityInfo"],
        isHasExtInfo: json["isHasExtInfo"],
        isHasExtTag: json["isHasExtTag"],
        isHasInfo: json["isHasInfo"],
    );

    Map<String, dynamic> toJson() => {
        "activityExtInfo": activityExtInfo,
        "activityExtTag": activityExtTag,
        "activityInfo": activityInfo,
        "isHasExtInfo": isHasExtInfo,
        "isHasExtTag": isHasExtTag,
        "isHasInfo": isHasInfo,
    };
}


///额外标签
class FluffyActivityExtTag {
    FluffyActivityExtTag({
        this.borderColor,
        this.fontColor,
        this.shadingColor,
        this.tagText,
    });

    
    ///边框颜色
    String? borderColor;
    
    ///字体颜色
    String? fontColor;
    
    ///底纹颜色
    String? shadingColor;
    
    ///标签文本
    String? tagText;

    factory FluffyActivityExtTag.fromJson(Map<String, dynamic> json) => FluffyActivityExtTag(
        borderColor: json["borderColor"],
        fontColor: json["fontColor"],
        shadingColor: json["shadingColor"],
        tagText: json["tagText"],
    );

    Map<String, dynamic> toJson() => {
        "borderColor": borderColor,
        "fontColor": fontColor,
        "shadingColor": shadingColor,
        "tagText": tagText,
    };
}

class ProductActivityInfoActivityTag {
    ProductActivityInfoActivityTag({
        this.borderColor,
        this.fontColor,
        this.shadingColor,
        this.tagText,
    });

    
    ///边框颜色
    String? borderColor;
    
    ///字体颜色
    String? fontColor;
    
    ///底纹颜色
    String? shadingColor;
    
    ///标签文本
    String? tagText;

    factory ProductActivityInfoActivityTag.fromJson(Map<String, dynamic> json) => ProductActivityInfoActivityTag(
        borderColor: json["borderColor"],
        fontColor: json["fontColor"],
        shadingColor: json["shadingColor"],
        tagText: json["tagText"],
    );

    Map<String, dynamic> toJson() => {
        "borderColor": borderColor,
        "fontColor": fontColor,
        "shadingColor": shadingColor,
        "tagText": tagText,
    };
}


///活动类型标签P264后新增,在浮层中用到
class ProductActivityInfoActivityTypeTag {
    ProductActivityInfoActivityTypeTag({
        this.borderColor,
        this.fontColor,
        this.shadingColor,
        this.tagText,
    });

    
    ///边框颜色
    String? borderColor;
    
    ///字体颜色
    String? fontColor;
    
    ///底纹颜色
    String? shadingColor;
    
    ///标签文本
    String? tagText;

    factory ProductActivityInfoActivityTypeTag.fromJson(Map<String, dynamic> json) => ProductActivityInfoActivityTypeTag(
        borderColor: json["borderColor"],
        fontColor: json["fontColor"],
        shadingColor: json["shadingColor"],
        tagText: json["tagText"],
    );

    Map<String, dynamic> toJson() => {
        "borderColor": borderColor,
        "fontColor": fontColor,
        "shadingColor": shadingColor,
        "tagText": tagText,
    };
}


///产品参数
class ProductParam {
    ProductParam({
        this.baseParams,
        this.extendParams,
    });

    
    ///基础参数
    List<BaseParam?>? baseParams;
    
    ///扩展参数
    List<ExtendParam?>? extendParams;

    factory ProductParam.fromJson(Map<String, dynamic> json) => ProductParam(
        baseParams: json["baseParams"] == null ? [] : List<BaseParam?>.from(json["baseParams"]!.map((x) => BaseParam.fromJson(x))),
        extendParams: json["extendParams"] == null ? [] : List<ExtendParam?>.from(json["extendParams"]!.map((x) => ExtendParam.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "baseParams": baseParams == null ? [] : List<dynamic>.from(baseParams!.map((x) => x!.toJson())),
        "extendParams": extendParams == null ? [] : List<dynamic>.from(extendParams!.map((x) => x!.toJson())),
    };
}

class BaseParam {
    BaseParam({
        this.propertyName,
        this.propertyValue,
    });

    
    ///属性名
    String? propertyName;
    
    ///属性值
    String? propertyValue;

    factory BaseParam.fromJson(Map<String, dynamic> json) => BaseParam(
        propertyName: json["propertyName"],
        propertyValue: json["propertyValue"],
    );

    Map<String, dynamic> toJson() => {
        "propertyName": propertyName,
        "propertyValue": propertyValue,
    };
}

class ExtendParam {
    ExtendParam({
        this.propertyName,
        this.propertyValue,
    });

    
    ///属性名
    String? propertyName;
    
    ///属性值
    String? propertyValue;

    factory ExtendParam.fromJson(Map<String, dynamic> json) => ExtendParam(
        propertyName: json["propertyName"],
        propertyValue: json["propertyValue"],
    );

    Map<String, dynamic> toJson() => {
        "propertyName": propertyName,
        "propertyValue": propertyValue,
    };
}


///商品服务信息
class ServiceInfo {
    ServiceInfo({
        this.serviceInfo,
        this.serviceTitle,
    });

    
    ///服务信息
    String? serviceInfo;
    
    ///服务标题
    String? serviceTitle;

    factory ServiceInfo.fromJson(Map<String, dynamic> json) => ServiceInfo(
        serviceInfo: json["serviceInfo"],
        serviceTitle: json["serviceTitle"],
    );

    Map<String, dynamic> toJson() => {
        "serviceInfo": serviceInfo,
        "serviceTitle": serviceTitle,
    };
}

class ShoppingActivityInfo {
    ShoppingActivityInfo({
        this.activityDesc,
        this.activityId,
        this.activityInfoFull,
        this.activityInfoFullText,
        this.activityName,
        this.activityStep,
        this.activityStepInfos,
        this.activityTags,
        this.activityTypeId,
        this.activityTypeName,
        this.activityTypeTag,
        this.activityUrl,
        this.activityUrlNew,
        this.giftOverlayDescription,
        this.haveStock,
        this.isRefundCoupon,
        this.limitNum,
        this.miniBuyNum,
        this.priceDesc,
        this.refundCouponInfo,
    });

    
    ///合约通描述
    String? activityDesc;
    
    ///活动id
    double? activityId;
    
    ///商品参与活动信息的各个阶梯主信息拼接(如:购满1送1赠品;购满2送2赠品;)
    String? activityInfoFull;
    
    ///商品参与活动主信息不含富文本
    String? activityInfoFullText;
    
    ///合约通名称
    String? activityName;
    
    ///活动阶段1未开始2进行中
    int? activityStep;
    
    ///活动各阶梯的信息
    List<ShoppingActivityInfoActivityStepInfo?>? activityStepInfos;
    
    ///活动的标签集合(如:满赠、返券)P264前在板块里和浮层里都用到,P264后只在板块用到
    List<ShoppingActivityInfoActivityTag?>? activityTags;
    
    ///
    ///活动类型的id1:每满赠;2:阶梯满赠;3:买本品赠本品;@com.qccr.bmarketcenter.facade.constant.GiftPromotionConstantsP243前在浮层用到
    int? activityTypeId;
    
    ///活动类型的名称
    String? activityTypeName;
    
    ///活动类型标签P264后新增,在浮层中用到
    ShoppingActivityInfoActivityTypeTag? activityTypeTag;
    
    ///活动H5页面地址
    String? activityUrl;
    
    ///活动页面地址,可能为scheml或h5
    String? activityUrlNew;
    
    ///赠品是否可叠加文案描述不可叠加:达成累计条件,以下赠品可任选一档获取,不可叠加可叠加:达成累计条件,以下赠品可叠加获取
    String? giftOverlayDescription;
    
    ///商品在活动中是否还有库存(实物库存虚拟库存、总限购)
    bool? haveStock;
    
    ///true为有返券P264前在浮层用到
    bool? isRefundCoupon;
    
    ///限购数
    int? limitNum;
    
    ///起购数
    int? miniBuyNum;
    
    ///商品在活动里的价格
    String? priceDesc;
    
    ///返券信息,isRefundCoupon为true时有值P264前在浮层用到
    String? refundCouponInfo;

    factory ShoppingActivityInfo.fromJson(Map<String, dynamic> json) => ShoppingActivityInfo(
        activityDesc: json["activityDesc"],
        activityId: json["activityId"],
        activityInfoFull: json["activityInfoFull"],
        activityInfoFullText: json["activityInfoFullText"],
        activityName: json["activityName"],
        activityStep: json["activityStep"],
        activityStepInfos: json["activityStepInfos"] == null ? [] : List<ShoppingActivityInfoActivityStepInfo?>.from(json["activityStepInfos"]!.map((x) => ShoppingActivityInfoActivityStepInfo.fromJson(x))),
        activityTags: json["activityTags"] == null ? [] : List<ShoppingActivityInfoActivityTag?>.from(json["activityTags"]!.map((x) => ShoppingActivityInfoActivityTag.fromJson(x))),
        activityTypeId: json["activityTypeId"],
        activityTypeName: json["activityTypeName"],
        activityTypeTag: json["activityTypeTag"],
        activityUrl: json["activityUrl"],
        activityUrlNew: json["activityUrlNew"],
        giftOverlayDescription: json["giftOverlayDescription"],
        haveStock: json["haveStock"],
        isRefundCoupon: json["isRefundCoupon"],
        limitNum: json["limitNum"],
        miniBuyNum: json["miniBuyNum"],
        priceDesc: json["priceDesc"],
        refundCouponInfo: json["refundCouponInfo"],
    );

    Map<String, dynamic> toJson() => {
        "activityDesc": activityDesc,
        "activityId": activityId,
        "activityInfoFull": activityInfoFull,
        "activityInfoFullText": activityInfoFullText,
        "activityName": activityName,
        "activityStep": activityStep,
        "activityStepInfos": activityStepInfos == null ? [] : List<dynamic>.from(activityStepInfos!.map((x) => x!.toJson())),
        "activityTags": activityTags == null ? [] : List<dynamic>.from(activityTags!.map((x) => x!.toJson())),
        "activityTypeId": activityTypeId,
        "activityTypeName": activityTypeName,
        "activityTypeTag": activityTypeTag,
        "activityUrl": activityUrl,
        "activityUrlNew": activityUrlNew,
        "giftOverlayDescription": giftOverlayDescription,
        "haveStock": haveStock,
        "isRefundCoupon": isRefundCoupon,
        "limitNum": limitNum,
        "miniBuyNum": miniBuyNum,
        "priceDesc": priceDesc,
        "refundCouponInfo": refundCouponInfo,
    };
}

class ShoppingActivityInfoActivityStepInfo {
    ShoppingActivityInfoActivityStepInfo({
        this.activityExtInfo,
        this.activityExtTag,
        this.activityInfo,
        this.isHasExtInfo,
        this.isHasExtTag,
        this.isHasInfo,
    });

    
    ///无
    String? activityExtInfo;
    
    ///无
    TentacledActivityExtTag? activityExtTag;
    
    ///无
    String? activityInfo;
    
    ///无
    bool? isHasExtInfo;
    
    ///无
    bool? isHasExtTag;
    
    ///是否有主要信息
    bool? isHasInfo;

    factory ShoppingActivityInfoActivityStepInfo.fromJson(Map<String, dynamic> json) => ShoppingActivityInfoActivityStepInfo(
        activityExtInfo: json["activityExtInfo"],
        activityExtTag: json["activityExtTag"],
        activityInfo: json["activityInfo"],
        isHasExtInfo: json["isHasExtInfo"],
        isHasExtTag: json["isHasExtTag"],
        isHasInfo: json["isHasInfo"],
    );

    Map<String, dynamic> toJson() => {
        "activityExtInfo": activityExtInfo,
        "activityExtTag": activityExtTag,
        "activityInfo": activityInfo,
        "isHasExtInfo": isHasExtInfo,
        "isHasExtTag": isHasExtTag,
        "isHasInfo": isHasInfo,
    };
}


///无
class TentacledActivityExtTag {
    TentacledActivityExtTag({
        this.borderColor,
        this.fontColor,
        this.shadingColor,
        this.tagText,
    });

    
    ///无
    String? borderColor;
    
    ///无
    String? fontColor;
    
    ///无
    String? shadingColor;
    
    ///无
    String? tagText;

    factory TentacledActivityExtTag.fromJson(Map<String, dynamic> json) => TentacledActivityExtTag(
        borderColor: json["borderColor"],
        fontColor: json["fontColor"],
        shadingColor: json["shadingColor"],
        tagText: json["tagText"],
    );

    Map<String, dynamic> toJson() => {
        "borderColor": borderColor,
        "fontColor": fontColor,
        "shadingColor": shadingColor,
        "tagText": tagText,
    };
}

class ShoppingActivityInfoActivityTag {
    ShoppingActivityInfoActivityTag({
        this.borderColor,
        this.fontColor,
        this.shadingColor,
        this.tagText,
    });

    
    ///无
    String? borderColor;
    
    ///无
    String? fontColor;
    
    ///无
    String? shadingColor;
    
    ///无
    String? tagText;

    factory ShoppingActivityInfoActivityTag.fromJson(Map<String, dynamic> json) => ShoppingActivityInfoActivityTag(
        borderColor: json["borderColor"],
        fontColor: json["fontColor"],
        shadingColor: json["shadingColor"],
        tagText: json["tagText"],
    );

    Map<String, dynamic> toJson() => {
        "borderColor": borderColor,
        "fontColor": fontColor,
        "shadingColor": shadingColor,
        "tagText": tagText,
    };
}


///活动类型标签P264后新增,在浮层中用到
class ShoppingActivityInfoActivityTypeTag {
    ShoppingActivityInfoActivityTypeTag({
        this.borderColor,
        this.fontColor,
        this.shadingColor,
        this.tagText,
    });

    
    ///无
    String? borderColor;
    
    ///无
    String? fontColor;
    
    ///无
    String? shadingColor;
    
    ///无
    String? tagText;

    factory ShoppingActivityInfoActivityTypeTag.fromJson(Map<String, dynamic> json) => ShoppingActivityInfoActivityTypeTag(
        borderColor: json["borderColor"],
        fontColor: json["fontColor"],
        shadingColor: json["shadingColor"],
        tagText: json["tagText"],
    );

    Map<String, dynamic> toJson() => {
        "borderColor": borderColor,
        "fontColor": fontColor,
        "shadingColor": shadingColor,
        "tagText": tagText,
    };
}

RmondJone avatar Mar 11 '22 16:03 RmondJone

对官方的PR合并无话可说,明摆着压根不给人提PR合并进去呗。真的搞笑,搞了一个代码自动检查,然后检查出来的全是他们自己代码的错误,然后不给通过。说真的,这样你真的不如闭源算了,没必要开源。这不是纯属恶心人嘛?

There is nothing to say about the official PR merger, and it is obvious that no one will mention the PR merger at all. It's really funny. They did an automatic code check, and then they checked out all the errors in their own code, and then they didn't pass. Seriously, this way you are really not as good as closed source, there is no need to open source. Isn't this outright disgusting?

RmondJone avatar Apr 09 '22 13:04 RmondJone

@schani Can you or anyone else review this please? Generation for dart is broken for a year now ...

khainke avatar Jun 15 '22 13:06 khainke

An update on this ?

radvansky-tomas avatar Jul 25 '22 05:07 radvansky-tomas

Why is no one merging this?

SemihGursoy avatar Dec 15 '22 22:12 SemihGursoy

I'll take a look this weekend.

dvdsgl avatar Dec 30 '22 16:12 dvdsgl

@RmondJone apologies. Our CI is back online and I've updated your branch, although I do not know how to make the tests work.

dvdsgl avatar Dec 31 '22 23:12 dvdsgl

@RmondJone apologies. Our CI is back online and I've updated your branch, although I do not know how to make the tests work.

I'll take a look later when I have time, which version of your node version is currently used? Is there a limit?

RmondJone avatar Jan 01 '23 01:01 RmondJone

I don't know if there is a problem with your detection mechanism. I can generate correct code normally when I run it locally. You can try it locally, I suspect that there is a certain problem with the CI script.

PS D:\github\RmondJone\quicktype> node dist\cli\index.js --lang dart .\test\inputs\json\samples\pokedex.json
// To parse this JSON data, do
//
//     final pokedex = pokedexFromJson(jsonString);

import 'dart:convert';

Pokedex? pokedexFromJson(String str) => Pokedex.fromJson(json.decode(str));

String pokedexToJson(Pokedex? data) => json.encode(data!.toJson());

class Pokedex {
    Pokedex({
        this.pokemon,
    });

    List<Pokemon?>? pokemon;

    factory Pokedex.fromJson(Map<String, dynamic> json) => Pokedex(
        pokemon: List<Pokemon?>.from(json["pokemon"]!.map((x) => Pokemon.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "pokemon": List<dynamic>.from(pokemon!.map((x) => x!.toJson())),
    };
}

class Pokemon {
    Pokemon({
        this.id,
        this.num,
        this.name,
        this.img,
        this.type,
        this.height,
        this.weight,
        this.candy,
        this.candyCount,
        this.egg,
        this.spawnChance,
        this.avgSpawns,
        this.spawnTime,
        this.multipliers,
        this.weaknesses,
        this.nextEvolution,
        this.prevEvolution,
    });

    int? id;
    String? num;
    String? name;
    String? img;
    List<Type?>? type;
    String? height;
    String? weight;
    String? candy;
    int? candyCount;
    Egg? egg;
    double? spawnChance;
    double? avgSpawns;
    String? spawnTime;
    List<double?>? multipliers;
    List<Type?>? weaknesses;
    List<Evolution?>? nextEvolution;
    List<Evolution?>? prevEvolution;

    factory Pokemon.fromJson(Map<String, dynamic> json) => Pokemon(
        id: json["id"],
        num: json["num"],
        name: json["name"],
        img: json["img"],
        type: List<Type?>.from(json["type"]!.map((x) => typeValues!.map[x])),
        height: json["height"],
        weight: json["weight"],
        candy: json["candy"],
        candyCount: json["candy_count"],
        egg: eggValues!.map[json["egg"]],
        spawnChance: json["spawn_chance"].toDouble(),
        avgSpawns: json["avg_spawns"].toDouble(),
        spawnTime: json["spawn_time"],
        multipliers: json["multipliers"] == null ? [] : List<double?>.from(json["multipliers"]!.map((x) => x.toDouble())),
        weaknesses: List<Type?>.from(json["weaknesses"]!.map((x) => typeValues!.map[x])),
        nextEvolution: json["next_evolution"] == null ? [] : List<Evolution?>.from(json["next_evolution"]!.map((x) => Evolution.fromJson(x))),
        prevEvolution: json["prev_evolution"] == null ? [] : List<Evolution?>.from(json["prev_evolution"]!.map((x) => Evolution.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "id": id,
        "num": num,
        "name": name,
        "img": img,
        "type": List<dynamic>.from(type!.map((x) => typeValues.reverse![x])),
        "height": height,
        "weight": weight,
        "candy": candy,
        "candy_count": candyCount,
        "egg": eggValues.reverse![egg],
        "spawn_chance": spawnChance,
        "avg_spawns": avgSpawns,
        "spawn_time": spawnTime,
        "multipliers": multipliers == null ? [] : List<dynamic>.from(multipliers!.map((x) => x)),
        "weaknesses": List<dynamic>.from(weaknesses!.map((x) => typeValues.reverse![x])),
        "next_evolution": nextEvolution == null ? [] : List<dynamic>.from(nextEvolution!.map((x) => x!.toJson())),
        "prev_evolution": prevEvolution == null ? [] : List<dynamic>.from(prevEvolution!.map((x) => x!.toJson())),
    };
}

enum Egg { THE_2_KM, NOT_IN_EGGS, THE_5_KM, THE_10_KM, OMANYTE_CANDY }

final eggValues = EnumValues({
    "Not in Eggs": Egg.NOT_IN_EGGS,
    "Omanyte Candy": Egg.OMANYTE_CANDY,
    "10 km": Egg.THE_10_KM,
    "2 km": Egg.THE_2_KM,
    "5 km": Egg.THE_5_KM
});

class Evolution {
    Evolution({
        this.num,
        this.name,
    });

    String? num;
    String? name;

    factory Evolution.fromJson(Map<String, dynamic> json) => Evolution(
        num: json["num"],
        name: json["name"],
    );

    Map<String, dynamic> toJson() => {
        "num": num,
        "name": name,
    };
}

enum Type { FIRE, ICE, FLYING, PSYCHIC, WATER, GROUND, ROCK, ELECTRIC, GRASS, FIGHTING, POISON, BUG, FAIRY, GHOST, DARK, STEEL, DRAGON, NORMAL }

final typeValues = EnumValues({
    "Bug": Type.BUG,
    "Dark": Type.DARK,
    "Dragon": Type.DRAGON,
    "Electric": Type.ELECTRIC,
    "Fairy": Type.FAIRY,
    "Fighting": Type.FIGHTING,
    "Fire": Type.FIRE,
    "Flying": Type.FLYING,
    "Ghost": Type.GHOST,
    "Grass": Type.GRASS,
    "Ground": Type.GROUND,
    "Ice": Type.ICE,
    "Normal": Type.NORMAL,
    "Poison": Type.POISON,
    "Psychic": Type.PSYCHIC,
    "Rock": Type.ROCK,
    "Steel": Type.STEEL,
    "Water": Type.WATER
});

class EnumValues<T> {
    Map<String, T> map;
    Map<T, String>? reverseMap;

    EnumValues(this.map);

    Map<T, String>? get reverse {
        reverseMap ??= map.map((k, v) => MapEntry(v, k));
        return reverseMap;
    }
}

RmondJone avatar Jan 01 '23 07:01 RmondJone

@RmondJone I have approved you to run our CI. You can see build failure messages now. There is no problem generating the code-the problem arises when our test harness tries to compile the generated Dart.

dvdsgl avatar Jan 01 '23 18:01 dvdsgl

@RmondJone I have approved you to run our CI. You can see build failure messages now. There is no problem generating the code-the problem arises when our test harness tries to compile the generated Dart.

OK, I have time to check recently. Maybe some scenes are not covered completely

RmondJone avatar Jan 03 '23 08:01 RmondJone

@dvdsgl I have adapted the ci script of DART. There is a problem with some test cases. In fact, the code generated by running alone has no compilation problem, but the CI reports an error. I masked these test cases, and then ran again and passed easily.

guohanlin@guohanlindeMacBook-Pro quicktype % FIXTURE=dart npm test

> [email protected] test
> jest && script/test

ts-jest[backports] (WARN) "[jest-config].globals.ts-jest.tsConfigFile" is deprecated, use "[jest-config].globals.ts-jest.tsConfig" instead.
ts-jest[backports] (WARN) Your Jest configuration is outdated. Use the CLI to help migrating it: ts-jest config:migrate <config-file>.
 PASS  src/__tests__/quicktype-core/language/TypeScriptFlow.test.ts
  jsonSchema to ts
    ✓ should convert with additionalProperties and specific type (39ms)
    ✓ should convert with additionalProperties and any type (12ms)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        1.261s
Ran all test suites.
* Running a subset of fixtures: dart
* Running 37 tests between 1 fixtures
* Forking 16 workers 👷🏽 👷🏽 👷🏾 👷🏽 👷🏿 👷🏽 👷🏿 👷🏾 👷🏾 👷🏻 👷🏽 👷🏿 👷🏼 👷🏻 👷🏻 👷🏻
* Running a subset of fixtures: dart
* Running a subset of fixtures: dart
* Running a subset of fixtures: dart
* Running a subset of fixtures: dart
* Running a subset of fixtures: dart
* Running a subset of fixtures: dart
* Running a subset of fixtures: dart
* Running a subset of fixtures: dart
* Running a subset of fixtures: dart
* Running a subset of fixtures: dart
* Running a subset of fixtures: dart
* Running a subset of fixtures: dart
* Running a subset of fixtures: dart
* Running a subset of fixtures: dart
* Running a subset of fixtures: dart
* Running a subset of fixtures: dart
* [13/37] dart() test/runs/dart-527e3d/empty-enum.json: 1145 ms
* [22/37] dart() test/runs/dart-320482/optional-union.json: 1172 ms
* [17/37] dart() test/runs/dart-ba69b0/name-style.json: 1300 ms
* [11/37] dart() test/runs/dart-c5335e/combined-enum.json: 1356 ms
* [21/37] dart() test/runs/dart-b235fd/number-map.json: 1277 ms
* [3/37] dart() test/runs/dart-ba867e/bug790.json: 1406 ms
* [14/37] dart() test/runs/dart-546bcc/identifiers.json: 1329 ms
* [25/37] dart() test/runs/dart-38322f/union-constructor-clash.json: 1371 ms
* [5/37] dart() test/runs/dart-f37428/bug863.json: 1561 ms
* [26/37] dart() test/runs/dart-fe9dcd/unions.json: 1421 ms
* [6/37] dart() test/runs/dart-3028d3/coin-pairs.json: 1665 ms
* [4/37] dart() test/runs/dart-3e8f1e/bug855-short.json: 1784 ms
* [19/37] dart() test/runs/dart-4615d3/no-classes.json: 1934 ms
* [27/37] dart() test/runs/dart-d9c8f9/url.json: 864 ms
* [20/37] dart() test/runs/dart-5f66d7/nst-test-suite.json: 2080 ms
* [34/37] dart() test/runs/dart-c6257d/simple-object.json: 824 ms
* [29/37] dart() test/runs/dart-cffffc/getting-started.json: 841 ms
* [24/37] dart() test/runs/dart-7de436/simple-identifiers.json: 2112 ms
* [36/37] dart() test/runs/dart-9d5f0b/us-avg-temperatures.json: 929 ms
* [31/37] dart() test/runs/dart-2753d2/kitchen-sink.json: 946 ms
* [35/37] dart() test/runs/dart-55ea1e/spotify-album.json: 956 ms
* [1/37] dart() test/runs/dart-4f9695/blns-object.json: 2565 ms
* [28/37] dart() test/runs/dart-22891d/bitcoin-block.json: 1179 ms
guohanlin@guohanlindeMacBook-Pro quicktype % 

RmondJone avatar Jan 03 '23 11:01 RmondJone

@dvdsgl I fixed the CI compilation problem caused by the prettier lock file. Please approve the CI script to run again

RmondJone avatar Jan 04 '23 02:01 RmondJone

Very good @RmondJone! The tests got pretty far: https://github.com/quicktype/quicktype/actions/runs/3834620089/jobs/6528090108#step:21:57

Are you able to run the tests locally? Use:

$ QUICKTEST=true FIXTURE=dart,schema-dart npm test

dvdsgl avatar Jan 04 '23 04:01 dvdsgl

Very good @RmondJone! The tests got pretty far: https://github.com/quicktype/quicktype/actions/runs/3834620089/jobs/6528090108#step:21:57

Are you able to run the tests locally? Use:

$ QUICKTEST=true FIXTURE=dart,schema-dart npm test

I use this command. There should also be some test cases in the schema that need to be masked. I'll look at them later.

FIXTURE=dart npm test

RmondJone avatar Jan 04 '23 04:01 RmondJone

@dvdsgl I have adapted the schema test script of Dart CI

guohanlin@guohanlindeMacBook-Pro quicktype % QUICKTEST=true FIXTURE=dart,schema-dart npm test

> [email protected] test
> jest && script/test

 PASS  src/__tests__/quicktype-core/language/TypeScriptFlow.test.ts
  jsonSchema to ts
    ✓ should convert with additionalProperties and specific type (38ms)
    ✓ should convert with additionalProperties and any type (12ms)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        1.44s, estimated 2s
Ran all test suites.
* Running a subset of fixtures: dart, schema-dart
* Running 87 tests between 2 fixtures
* Forking 16 workers 👷🏻 👷🏻 👷🏼 👷🏻 👷🏼 👷🏻 👷🏿 👷🏼 👷🏾 👷🏽 👷🏻 👷🏿 👷🏿 👷🏾 👷🏽 👷🏿
* Running a subset of fixtures: dart, schema-dart
* Running a subset of fixtures: dart, schema-dart
* Running a subset of fixtures: dart, schema-dart
* Running a subset of fixtures: dart, schema-dart
* Running a subset of fixtures: dart, schema-dart
* Running a subset of fixtures: dart, schema-dart
* Running a subset of fixtures: dart, schema-dart
* Running a subset of fixtures: dart, schema-dart
* Running a subset of fixtures: dart, schema-dart
* Running a subset of fixtures: dart, schema-dart
* Running a subset of fixtures: dart, schema-dart
* Running a subset of fixtures: dart, schema-dart
* Running a subset of fixtures: dart, schema-dart
* Running a subset of fixtures: dart, schema-dart
* Running a subset of fixtures: dart, schema-dart
* Running a subset of fixtures: dart, schema-dart
* [19/87] dart() test/runs/dart-745fb8/no-classes.json: 932 ms
* [13/87] dart() test/runs/dart-2cdf89/empty-enum.json: 982 ms
* [24/87] dart() test/runs/dart-e1ef48/simple-identifiers.json: 1036 ms
* [22/87] dart() test/runs/dart-ab27fe/optional-union.json: 1070 ms
* [17/87] dart() test/runs/dart-263bc3/name-style.json: 1166 ms
* [3/87] dart() test/runs/dart-eeeb27/bug790.json: 1280 ms
* [14/87] dart() test/runs/dart-1212ab/identifiers.json: 1185 ms
* [11/87] dart() test/runs/dart-11f17f/combined-enum.json: 1278 ms
* [21/87] dart() test/runs/dart-bdab23/number-map.json: 1245 ms
* [25/87] dart() test/runs/dart-ac1d36/union-constructor-clash.json: 1230 ms
* [5/87] dart() test/runs/dart-770247/bug863.json: 1410 ms
* [26/87] dart() test/runs/dart-d82108/unions.json: 1347 ms
* [6/87] dart() test/runs/dart-12211a/coin-pairs.json: 1500 ms
* [4/87] dart() test/runs/dart-0c2633/bug855-short.json: 1605 ms
* [45/87] schema-dart() test/runs/schema-dart-4fcdd3/date-time-or-string.schema (0 files): 73 ms
* [27/87] dart() test/runs/dart-499c7f/url.json: 1002 ms
* [42/87] schema-dart() test/runs/schema-dart-4b0818/class-with-additional.schema: 839 ms
* [38/87] schema-dart() test/runs/schema-dart-cce4fb/accessors.schema: 934 ms
* [36/87] dart() test/runs/dart-a19741/us-avg-temperatures.json: 1029 ms
* [50/87] schema-dart() test/runs/schema-dart-0c17d4/enum-with-values.schema (0 files): 26 ms
* [35/87] dart() test/runs/dart-7ffffe/spotify-album.json: 1080 ms
* [29/87] dart() test/runs/dart-baf603/getting-started.json: 1223 ms
* [44/87] schema-dart() test/runs/schema-dart-844351/cut-enum.schema: 937 ms
* [31/87] dart() test/runs/dart-14e43f/kitchen-sink.json: 1404 ms
* [53/87] schema-dart() test/runs/schema-dart-8aada8/id-no-address.schema: 716 ms
* [48/87] schema-dart() test/runs/schema-dart-4d01fd/direct-union.schema: 791 ms
* [54/87] schema-dart() test/runs/schema-dart-2ab9b9/id-root.schema: 722 ms
* [60/87] schema-dart() test/runs/schema-dart-44b968/intersection-nested.schema (0 files): 25 ms
* [55/87] schema-dart() test/runs/schema-dart-e28e5d/implicit-all-of.schema: 752 ms
* [34/87] dart() test/runs/dart-f50273/simple-object.json: 1907 ms
* [28/87] dart() test/runs/dart-7fb1f0/bitcoin-block.json: 2208 ms
* [20/87] dart() test/runs/dart-544968/nst-test-suite.json: 3212 ms
* [43/87] schema-dart() test/runs/schema-dart-b36fe8/constructor.schema: 1873 ms
* [1/87] dart() test/runs/dart-46df74/blns-object.json: 3890 ms
* [46/87] schema-dart() test/runs/schema-dart-74e59b/date-time.schema: 2189 ms
* [47/87] schema-dart() test/runs/schema-dart-e1bb30/description.schema (2 files): 1828 ms
* [77/87] schema-dart() test/runs/schema-dart-6e93f1/required-draft3.schema (0 files): 15 ms
* [39/87] schema-dart() test/runs/schema-dart-31ad61/any.schema (3 files): 2562 ms
* [79/87] schema-dart() test/runs/schema-dart-c16579/required.schema (0 files): 32 ms
* [81/87] schema-dart() test/runs/schema-dart-a3b1b8/strict-optional.schema (0 files): 23 ms
* [52/87] schema-dart() test/runs/schema-dart-585544/go-schema-pattern-properties.schema (2 files): 1785 ms
* [65/87] schema-dart() test/runs/schema-dart-90deca/minmax.schema: 1023 ms
* [66/87] schema-dart() test/runs/schema-dart-0eb90e/minmaxlength.schema: 1024 ms
* [69/87] schema-dart() test/runs/schema-dart-ac6bfc/non-standard-ref.schema: 1101 ms
* [76/87] schema-dart() test/runs/schema-dart-29cbc9/renaming-bug.schema (0 files): 499 ms
* [72/87] schema-dart() test/runs/schema-dart-83739b/pattern.schema: 1068 ms
* [78/87] schema-dart() test/runs/schema-dart-b4f868/required-non-properties.schema: 805 ms
* [74/87] schema-dart() test/runs/schema-dart-0d9e31/ref-id-files.schema: 861 ms
* [58/87] schema-dart() test/runs/schema-dart-1cc347/integer-float-union.schema (2 files): 1797 ms
* [82/87] schema-dart() test/runs/schema-dart-432793/top-level-enum.schema: 846 ms
* [83/87] schema-dart() test/runs/schema-dart-4b1094/tuple.schema: 760 ms
* [85/87] schema-dart() test/runs/schema-dart-447c41/union.schema: 741 ms
* [70/87] schema-dart() test/runs/schema-dart-83aba9/object-type-required.schema (2 files): 1706 ms
* [57/87] schema-dart() test/runs/schema-dart-fcd1ee/implicit-one-of.schema (2 files): 2456 ms
* [41/87] schema-dart() test/runs/schema-dart-bff7a5/class-map-union.schema (4 files): 3942 ms
* [87/87] schema-dart() test/runs/schema-dart-86478e/vega-lite.schema (0 files): 1360 ms
* [56/87] schema-dart() test/runs/schema-dart-bf8601/implicit-class-array-union.schema (5 files): 3254 ms
* [71/87] schema-dart() test/runs/schema-dart-33f6a3/optional-any.schema (2 files): 2411 ms
* [84/87] schema-dart() test/runs/schema-dart-8ab005/union-list.schema (3 files): 1635 ms
* [67/87] schema-dart() test/runs/schema-dart-efdeea/multi-type-enum.schema (3 files): 2807 ms
guohanlin@guohanlindeMacBook-Pro quicktype % 

RmondJone avatar Jan 06 '23 06:01 RmondJone

@RmondJone 🥳 it is released https://app.quicktype.io/

I don't know Dart, but shouldn't it be possible to have non-nullable properties? Looks like it's always this:

class Welcome {
    Welcome({
        this.greeting,
        this.instructions,
    });

    String? greeting;
    List<String?>? instructions;
}

I would expect to see:

class Welcome {
    Welcome({
        this.greeting,
        this.instructions,
    });

    String greeting;
    List<String> instructions;
}

dvdsgl avatar Jan 07 '23 15:01 dvdsgl

@RmondJone 🥳 it is released https://app.quicktype.io/

I don't know Dart, but shouldn't it be possible to have non-nullable properties? Looks like it's always this:

class Welcome {
    Welcome({
        this.greeting,
        this.instructions,
    });

    String? greeting;
    List<String?>? instructions;
}

I would expect to see:

class Welcome {
    Welcome({
        this.greeting,
        this.instructions,
    });

    String greeting;
    List<String> instructions;
}

The default value I designed is null security. You can control whether it is null security through the property nullSafety. The default value is true, and you can set it to false.

export const dartOptions = {
    nullSafety: new BooleanOption("null-safety", "Null Safety", true),
    justTypes: new BooleanOption("just-types", "Types only", false),
    codersInClass: new BooleanOption("coders-in-class", "Put encoder & decoder in Class", false),
    methodNamesWithMap: new BooleanOption("from-map", "Use method names fromMap() & toMap()", false),
    requiredProperties: new BooleanOption("required-props", "Make all properties required", false),
    finalProperties: new BooleanOption("final-props", "Make all properties final", false),
    generateCopyWith: new BooleanOption("copy-with", "Generate CopyWith method", false),
    useFreezed: new BooleanOption("use-freezed", "Generate class definitions with @freezed compatibility", false),
    useHive: new BooleanOption("use-hive", "Generate annotations for Hive type adapters", false),
    partName: new StringOption("part-name", "Use this name in `part` directive", "NAME", "")
};

A null-safety menu should be added here, but I don't know if this page is in the project? I don't know where to modify it. If it's clear to you, you could add this toggle button to allow the user to toggle between null-safety and non-null-safety. It is recommended to default to null-safety, because currently Dart basically uses the null-safe version, and there are very few non-null-safe versions.

image

RmondJone avatar Jan 08 '23 01:01 RmondJone

@RmondJone 🥳 it is released https://app.quicktype.io/

I don't know Dart, but shouldn't it be possible to have non-nullable properties? Looks like it's always this:

class Welcome {
    Welcome({
        this.greeting,
        this.instructions,
    });

    String? greeting;
    List<String?>? instructions;
}

I would expect to see:

class Welcome {
    Welcome({
        this.greeting,
        this.instructions,
    });

    String greeting;
    List<String> instructions;
}

@dvdsgl Looking at this PR, I think this should be the problem. I didn't add nullSafety in the getOptions method, so https://app.quicktype.io/ didn't render the Null Safety toggle button. #2085

RmondJone avatar Jan 08 '23 02:01 RmondJone

when you say null security do you mean all properties are nullable? because in dart, properties are meant to either be nullable or not depending on whether their valuer can actually be null. If i generate code right now, all properties are marked with ? even though some of them are never null, and should therefore not be. Making all properties nullable by default is not a great solution, because if I want safe types, I now have to go through every single type again.

clragon avatar Jan 08 '23 14:01 clragon

when you say null security do you mean all properties are nullable? because in dart, properties are meant to either be nullable or not depending on whether their valuer can actually be null. If i generate code right now, all properties are marked with ? even though some of them are never null, and should therefore not be. Making all properties nullable by default is not a great solution, because if I want safe types, I now have to go through every single type again.

Null safety should be like this, and some null judgments should be made during code writing to ensure that null pointer exceptions will not be reported in actual use

RmondJone avatar Jan 08 '23 14:01 RmondJone

no, I do not believe that is true. If I know that the model I will be getting from the server will never contain a null value, then it is pointless to mark it as nullable, and therefore pointless to generate it as such. if all my objects have an id field and its always a number and can never be null because of how SQL works, then why should I add ? to the field, or use ! to assert that it is not null?

quicktype wont be able to infere what fields can be nullable or not from a single model, but it can easily figure it out when presented with a whole list of models. If I paste 80 models into it, it can see what fields are always present and which ones are not. This behaviour would be immensly helpful, as compared to just marking all fields nullable. If it does not do that, then adding ? to the fields would be entirely worthless to me, as I have to go and check and add the ? (or remove them) by hand anyways.

I in fact believe that if quicktype has no data on whether a field should be nullable or not, then it should default to not being nullable. Introducing fields as nullable by default just means developers cant be sure whether the field is actually null or not and they will either use unnecessary if statements, or assert the variable not being null with ! which can then lead to unexpected runtime errors. I also assume that more fields will be non-nullable than the ones that will be. We also have to think about what kind of message making all fields nullable is to beginners of the dart language.

clragon avatar Jan 08 '23 14:01 clragon

no, I do not believe that is true. If I know that the model I will be getting from the server will never contain a null value, then it is pointless to mark it as nullable, and therefore pointless to generate it as such. if all my objects have an id field and its always a number and can never be null because of how SQL works, then why should I add ? to the field, or use ! to assert that it is not null?

quicktype wont be able to infere what fields can be nullable or not from a single model, but it can easily figure it out when presented with a whole list of models. If I paste 80 models into it, it can see what fields are always present and which ones are not. This behaviour would be immensly helpful, as compared to just marking all fields nullable. If it does not do that, then adding ? to the fields would be entirely worthless to me, as I have to go and check and add the ? (or remove them) by hand anyways.

I in fact believe that if quicktype has no data on whether a field should be nullable or not, then it should default to not being nullable. Introducing fields as nullable by default just means developers cant be sure whether the field is actually null or not and they will either use unnecessary if statements, or assert the variable not being null with ! which can then lead to unexpected runtime errors. I also assume that more fields will be non-nullable than the ones that will be. We also have to think about what kind of message making all fields nullable is to beginners of the dart language.

The background data may return empty data like {} because of an error, so I set all attributes to be empty, and I think there is no problem with this. If you are sure that background data will never have this kind of return, you can manually remove the attributes you confirmed ? And add the require keyword

RmondJone avatar Jan 08 '23 15:01 RmondJone

I believe returning {} when there is an error to be a terrible API design. if your server has an error, it should return a http error status so that you get an exception in your code. silently swallowing the error and having a completely empty model that has no data inside of it is not acceptable in my opinion and I dont think this should be the standard for anything, especially not the bases on which a code generator is built. This would even mean that your entire UI has to be built in a way where every single field can be null. I dont see how this would be desirable in any way.

clragon avatar Jan 08 '23 15:01 clragon

@RmondJone that is not how other quicktype languages work. It should be possible to create non-nullable properties when the schema requires that or JSON samples imply that.

dvdsgl avatar Jan 08 '23 17:01 dvdsgl

I don’t know Dart well, but I have started what I think we should do in #2087

dvdsgl avatar Jan 08 '23 17:01 dvdsgl

I believe returning {} when there is an error to be a terrible API design. if your server has an error, it should return a http error status so that you get an exception in your code. silently swallowing the error and having a completely empty model that has no data inside of it is not acceptable in my opinion and I dont think this should be the standard for anything, especially not the bases on which a code generator is built. This would even mean that your entire UI has to be built in a way where every single field can be null. I dont see how this would be desirable in any way.

Okay, please provide what you think is the most reasonable idea. We design according to the ideas you provide. How can I tell from the backend data that this field must be non-nullable?

RmondJone avatar Jan 08 '23 22:01 RmondJone

I believe returning {} when there is an error to be a terrible API design. if your server has an error, it should return a http error status so that you get an exception in your code. silently swallowing the error and having a completely empty model that has no data inside of it is not acceptable in my opinion and I dont think this should be the standard for anything, especially not the bases on which a code generator is built. This would even mean that your entire UI has to be built in a way where every single field can be null. I dont see how this would be desirable in any way.

Let's all come here to discuss, this PR is already merged. #2087

RmondJone avatar Jan 08 '23 22:01 RmondJone

@clragon This problem has been fixed. Pay attention to this PR #2135

RmondJone avatar Jan 18 '23 09:01 RmondJone