typewriter-Example
January 8, 2018 · View on GitHub
本repo收藏着typewriter生成的代码样例,说了太多,直接上码。
Swift
以下是Swift的样例,首先是JSON数据交换格式文件:
{
"generate" : "WirelessChargingModel",
"inherit" : "TypewriterBaseModel",
"implement" : ["Error"],
"options" : ["constructOnly"],
"memberVariable" : {
"length" : {
"type" : "String",
"rewrittenName" : "cableLength"
},
"manufacturerNumber" : {
"type" : "String",
"flatten" : "equipment.info"
},
"powerSource" : {"type" : "String"}
}
}
typewriter将它翻译成:
public struct WirelessChargingModel: Error, Codable {
enum CodingKeys: String, CodingKey {
case length = "cableLength"
case powerSource
case equipment
}
enum equipmentCodingKeys: String, CodingKey {
case info
}
enum infoCodingKeys: String, CodingKey {
case manufacturerNumber
}
public let length: String
public let powerSource: String
public let manufacturerNumber: String
static func modelWithJson(json: Data) throws -> WirelessChargingModel {
let model = try JSONDecoder().decode(WirelessChargingModel.self, from: json)
return model
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.length = try container.decode(String.self, forKey: .length)
self.powerSource = try container.decode(String.self, forKey: .powerSource)
let equipmentContainer = try container.nestedContainer(keyedBy: equipmentCodingKeys.self, forKey: .equipment)
let infoContainer = try equipmentContainer.nestedContainer(keyedBy: infoCodingKeys.self, forKey: .info)
self.manufacturerNumber = try infoContainer.decode(String.self, forKey: .manufacturerNumber)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(length, forKey: .length)
try container.encode(powerSource, forKey: .powerSource)
var equipmentContainer = container.nestedContainer(keyedBy: equipmentCodingKeys.self, forKey: .equipment)
var infoContainer = equipmentContainer.nestedContainer(keyedBy: infoCodingKeys.self, forKey: .info)
try infoContainer.encode(manufacturerNumber, forKey: .manufacturerNumber)
}
}
ObjC
以下是ObjC样例,首先是JSON数据交换格式:
{
"generate" : "WirelessChargingModel",
"inherit" : "TypewriterBaseModel",
"implement" : ["NSObject"],
"options" : ["constructOnly"],
"memberVariable" : {
"length" : {
"type" : "String",
"rewrittenName" : "cableLength"
},
"manufacturerNumber" : {
"type" : "String",
"flatten" : "equipment.info"
},
"powerSource" : {"type" : "String"}
}
}
typewriter将它翻译成:
@interface WirelessChargingModel : TypewriterBaseModel<NSObject>
@property (nonatomic, readonly, copy) NSString *length;
@property (nonatomic, readonly, copy) NSString *powerSource;
@property (nonatomic, readonly, copy) NSString *manufacturerNumber;
+ (nullable instancetype)modelWithJSON:(id)json;
- (nullable instancetype)initWithJSON:(id)json;
@end
@implementation WirelessChargingModel
+ (nullable instancetype)modelWithJSON:(id)json
{
return [[self alloc] initWithJSON:json];
}
- (nullable instancetype)initWithJSON:(id)json
{
NSParameterAssert(json);
if (!(self = [super init])) {
return nil;
}
if (![self propertyMapWithJSON:json]) {
return nil;
}
return self;
}
+ (NSDictionary *)customPropertyMapper
{
return @{@"manufacturerNumber" : @"equipment.info.manufacturerNumber",
@"length" : @"cableLength"};
}
- (void)setLength:(NSString *)length
{
_length = length;
}
- (void)setPowerSource:(NSString *)powerSource
{
_powerSource = powerSource;
}
- (void)setManufacturerNumber:(NSString *)manufacturerNumber
{
_manufacturerNumber = manufacturerNumber;
}
@end
接下来是ProtocolBuffer:
#pragma Typewriter(generate=UserPbModel)
#pragma Typewriter(inherit=TypewriterBaseModel)
#pragma Typewriter(implement={NSObject})
#pragma Typewriter(filter={success})
#pragma Typewriter(predicateFilter=SELF CONTAINS %@ OR SELF CONTAINS %@, result, _Count)
#pragma Typewriter(immutable)
#pragma Typewriter(rewritten={Rewritten(on=userName,name=name),\
Rewritten(on=educationEnum,name=education,type=EducationLevel),\
Rewritten(on=pet,type=$ref(PetPb.pbobjc.h)),\
Rewritten(on=ownHousesArray,name=houses,type=$ref(HousePb.pbobjc.h)),\
Rewritten(on=wardrobes,type=$ref(ClothesPb.pbobjc.h))})
@interface UserPb : GPBMessage
@property(nonatomic, readwrite, copy, null_resettable) NSString *resultMessage;
@property(nonatomic, readwrite, copy, null_resettable) NSString *resultCode;
@property(nonatomic, readwrite) BOOL success;
@property(nonatomic, readwrite, copy, null_resettable) NSString *userName;
@property(nonatomic, readwrite, copy, null_resettable) NSString *favouriteSport;
@property(nonatomic, readwrite, copy, null_resettable) NSString *favouriteMovie;
@property(nonatomic, readwrite) BOOL hasMarried;
@property(nonatomic, readwrite, copy, null_resettable) NSString *educationEnum;
@property(nonatomic, readwrite) uint32_t age;
@property(nonatomic, readwrite) int32_t psychologicalAge;
@property(nonatomic, readwrite, strong, null_resettable) PetPb *pet;
/** Test to see if @c pet has been set. */
@property(nonatomic, readwrite) BOOL hasPet;
@property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<HousePb*> *ownHousesArray;
/** The number of items in @c ownHousesArray without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger ownHousesArray_Count;
@property(nonatomic, readwrite, strong, null_resettable) NSMutableDictionary<NSString*, ClothesPb*> *wardrobes;
/** The number of items in @c wardrobes without causing the array to be created. */
@property(nonatomic, readonly) NSUInteger wardrobes_Count;
@end
typewriter将它翻译成:
@interface UserPbModel : TypewriterBaseModel<NSObject>
@property (nonatomic, readwrite, copy, nullable) NSString *objectId;
@property (nonatomic, readonly, copy) NSString *name;
@property (nonatomic, readonly, copy) NSString *favouriteSport;
@property (nonatomic, readonly, copy) NSString *favouriteMovie;
@property (nonatomic, readonly, assign) BOOL hasMarried;
@property (nonatomic, readonly, assign) EducationLevel education;
@property (nonatomic, readonly, assign) UInt32 age;
@property (nonatomic, readonly, assign) SInt32 psychologicalAge;
@property (nonatomic, readonly, strong) PetPbModel *pet;
@property (nonatomic, readonly, assign) BOOL hasPet;
@property (nonatomic, readonly, strong) NSArray<HousePbModel *> *houses;
@property (nonatomic, readonly, strong) NSDictionary<NSString *, ClothesPbModel *> *wardrobes;
+ (nullable instancetype)modelWithUserPb:(UserPb *)prototype objectId:(nullable NSString *)objectId;
- (nullable instancetype)initWithUserPb:(UserPb *)prototype objectId:(nullable NSString *)objectId;
- (instancetype)initWithUserPbModelBuilder:(UserPbModelBuilder *)builder;
- (instancetype)mergeWithBlock:(void(^)(UserPbModelBuilder *builder))block;
@end
@interface UserPbModelBuilder : TypewriterBaseModel
@property (nonatomic, readwrite, copy, nullable) NSString *objectId;
@property (nonatomic, readwrite, copy) NSString *name;
@property (nonatomic, readwrite, copy) NSString *favouriteSport;
@property (nonatomic, readwrite, copy) NSString *favouriteMovie;
@property (nonatomic, readwrite, assign) BOOL hasMarried;
@property (nonatomic, readwrite, assign) EducationLevel education;
@property (nonatomic, readwrite, assign) UInt32 age;
@property (nonatomic, readwrite, assign) SInt32 psychologicalAge;
@property (nonatomic, readwrite, strong) PetPbModel *pet;
@property (nonatomic, readwrite, assign) BOOL hasPet;
@property (nonatomic, readwrite, strong) NSArray<HousePbModel *> *houses;
@property (nonatomic, readwrite, strong) NSDictionary<NSString *, ClothesPbModel *> *wardrobes;
- (instancetype)initWithUserPbModel:(UserPbModel *)model;
- (UserPbModel *)build;
@end
@interface UserPbModel (Extension)
+ (void)unidirectionalDataflow:(UserPbModel *)model objectId:(NSString *)objectId;
@end
@implementation UserPbModel
- (instancetype)init UNAVAILABLE_ATTRIBUTE
{
NSAssert(NO, @"please use designed initializer instead!");
return nil;
}
+ (nullable instancetype)modelWithUserPb:(UserPb *)prototype objectId:(nullable NSString *)objectId
{
return [[self alloc] initWithUserPb:prototype objectId:objectId];
}
- (nullable instancetype)initWithUserPb:(UserPb *)prototype objectId:(nullable NSString *)objectId
{
NSParameterAssert(prototype);
if (!(self = [super init])) {
return nil;
}
[self propertyMapWithPrototype:prototype mapping:@{@"name" : @"userName",
@"favouriteSport" : @"favouriteSport",
@"favouriteMovie" : @"favouriteMovie",
@"hasMarried" : @"hasMarried",
@"age" : @"age",
@"psychologicalAge" : @"psychologicalAge",
@"hasPet" : @"hasPet"}];
self->_objectId = objectId;
self->_education = [prototype.educationEnum intValue];
self->_pet = [self transformModelFromPrototype:prototype.pet];
self->_houses = [self transformModelFromPrototype:prototype.ownHousesArray];
self->_wardrobes = [self transformModelFromPrototype:prototype.wardrobes];
[UserPbModel unidirectionalDataflow:self objectId:self.objectId];
return self;
}
- (nullable id)transformModelFromPrototype:(id)prototype
{
if (!prototype) {
return nil;
}
if ([prototype isKindOfClass:[HousePb class]]) {
HousePbModel * model = [HousePbModel modelWithHousePb:prototype];
return model;
}
if ([prototype isKindOfClass:[ClothesPb class]]) {
ClothesPbModel * model = [ClothesPbModel modelWithClothesPb:prototype objectId:self.objectId];
return model;
}
if ([prototype isKindOfClass:[PetPb class]]) {
PetPbModel * model = [PetPbModel modelWithPetPb:prototype];
return model;
}
return [super transformModelFromPrototype:prototype];
}
- (instancetype)initWithUserPbModelBuilder:(UserPbModelBuilder *)builder
{
NSParameterAssert(builder);
if (!(self = [super init])) {
return self;
}
[self propertyMapWithPrototype:builder mapping:@{@"objectId": @"objectId",
@"name": @"name",
@"favouriteSport": @"favouriteSport",
@"favouriteMovie": @"favouriteMovie",
@"hasMarried": @"hasMarried",
@"education": @"education",
@"age": @"age",
@"psychologicalAge": @"psychologicalAge",
@"pet": @"pet",
@"hasPet": @"hasPet",
@"houses": @"houses",
@"wardrobes": @"wardrobes"}];
[UserPbModel unidirectionalDataflow:self objectId:self.objectId];
return self;
}
- (instancetype)mergeWithBlock:(void(^)(UserPbModelBuilder *builder))block
{
NSParameterAssert(block);
UserPbModelBuilder *builder = [[UserPbModelBuilder alloc] initWithUserPbModel:self];
block(builder);
return [builder build];
}
@end
@implementation UserPbModelBuilder
- (instancetype)initWithUserPbModel:(UserPbModel *)model
{
NSParameterAssert(model);
if (!(self = [super init])) {
return self;
}
[self propertyMapWithPrototype:model mapping:@{@"objectId": @"objectId",
@"name": @"name",
@"favouriteSport": @"favouriteSport",
@"favouriteMovie": @"favouriteMovie",
@"hasMarried": @"hasMarried",
@"education": @"education",
@"age": @"age",
@"psychologicalAge": @"psychologicalAge",
@"pet": @"pet",
@"hasPet": @"hasPet",
@"houses": @"houses",
@"wardrobes": @"wardrobes"}];
return self;
}
- (UserPbModel *)build
{
return [[UserPbModel alloc] initWithUserPbModelBuilder:self];
}
@end
@implementation UserPbModel (Extension)
+ (void)unidirectionalDataflow:(UserPbModel *)model objectId:(NSString *)objectId
{
// unidirectional data flow
}
@end
Java
以下是Java的样例,独特的一点是与JSON相关的Annotation需要生成后手动标记添加,首先是JSON数据交换格式文件:
{
"generate" : "WirelessChargingModel",
"inherit" : "TypewriterBaseModel",
"implement" : ["Serializable"],
"options" : ["constructOnly"],
"memberVariable" : {
"length" : {
"type" : "String",
"rewrittenName" : "cableLength",
"annotation" : "@JSONField(name = \"cableLength\")"
},
"manufacturerNumber" : {
"type" : "String",
"flatten" : "equipment.info"
},
"powerSource" : {"type" : "String"}
}
}
typewriter将它翻译成:
public class WirelessChargingModel extends TypewriterBaseModel implements Serializable {
@JSONField(name = "cableLength")
public final String length;
public final String powerSource;
public final String manufacturerNumber;
public static WirelessChargingModel modelWithJSON(String json) {
return WirelessChargingModel.fieldsMapWithJSON(json, WirelessChargingModel.class);
}
@JSONCreator
public WirelessChargingModel(@JSONField(name = "powerSource") String powerSource,
@JSONField(name = "cableLength") String length,
@JSONField(name = "manufacturerNumber") String manufacturerNumber) {
this.length = length;
this.powerSource = powerSource;
this.manufacturerNumber = manufacturerNumber;
}
@SuppressWarnings("unused")
public static Map<String, String> customFieldsMapper() {
Map<String, String> mapper = new HashMap<>();
mapper.put("manufacturerNumber", "equipment.info.manufacturerNumber");
return mapper;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof WirelessChargingModel)) return false;
WirelessChargingModel other = (WirelessChargingModel) obj;
return (length != null ? length.equals(other.length) : other.length == null)
&& (powerSource != null ? powerSource.equals(other.powerSource) : other.powerSource == null)
&& (manufacturerNumber != null ? manufacturerNumber.equals(other.manufacturerNumber) : other.manufacturerNumber == null);
}
@Override
public int hashCode() {
int result = super.hashCode() != 0 ? super.hashCode() : 1;
result = result * 37 + (length != null ? length.hashCode() : 0);
result = result * 37 + (powerSource != null ? powerSource.hashCode() : 0);
result = result * 37 + (manufacturerNumber != null ? manufacturerNumber.hashCode() : 0);
return result;
}
}
接下来是wire:
@RepeatableTypewriter({
@Typewriter(generate = "UserPbModel"),
@Typewriter(inherit = "TypewriterBaseModel"),
@Typewriter(implement = {"Serializable"}),
@Typewriter(filter = {"success"}),
@Typewriter(predicateFilter = "SELF CONTAINS %@, result"),
@Typewriter(TypewriterOption.immutable),
@Typewriter(rewritten = {@Rewritten(on = "userName", name = "name"),
@Rewritten(on = "educationEnum", name = "education", type = "EducationLevel"),
@Rewritten(on = "pet", type = "$ref(PetPb.java)"),
@Rewritten(on = "ownHouses", name = "houses", type = "$ref(HousePb.java)"),
@Rewritten(on = "wardrobes", type = "$ref(ClothesPb.java)")})
})
public final class UserPb extends Message<UserPb, UserPb.Builder> {
public static final ProtoAdapter<UserPb> ADAPTER = new ProtoAdapter_UserPb();
private static final long serialVersionUID = 0L;
public static final String DEFAULT_RESULTMESSAGE = "";
public static final String DEFAULT_RESULTCODE = "";
public static final Boolean DEFAULT_SUCCESS = false;
public static final String DEFAULT_USERNAME = "";
public static final String DEFAULT_FAVOURITESPORT = "";
public static final String DEFAULT_FAVOURITEMOVIE = "";
public static final Boolean DEFAULT_HASMARRIED = false;
public static final String DEFAULT_EDUCATIONENUM = "";
public static final Integer DEFAULT_AGE = 0;
public static final Integer DEFAULT_PSYCHOLOGICALAGE = 0;
@WireField(
tag = 1,
adapter = "com.squareup.wire.ProtoAdapter#STRING"
)
public final String resultMessage;
@WireField(
tag = 2,
adapter = "com.squareup.wire.ProtoAdapter#STRING"
)
public final String resultCode;
@WireField(
tag = 3,
adapter = "com.squareup.wire.ProtoAdapter#BOOL"
)
public final Boolean success;
@WireField(
tag = 4,
adapter = "com.squareup.wire.ProtoAdapter#STRING"
)
public final String userName;
@WireField(
tag = 5,
adapter = "com.squareup.wire.ProtoAdapter#STRING"
)
public final String favouriteSport;
@WireField(
tag = 6,
adapter = "com.squareup.wire.ProtoAdapter#STRING"
)
public final String favouriteMovie;
@WireField(
tag = 7,
adapter = "com.squareup.wire.ProtoAdapter#BOOL"
)
public final Boolean hasMarried;
@WireField(
tag = 8,
adapter = "com.squareup.wire.ProtoAdapter#STRING"
)
public final String educationEnum;
@WireField(
tag = 9,
adapter = "com.squareup.wire.ProtoAdapter#UINT32"
)
public final Integer age;
@WireField(
tag = 10,
adapter = "com.squareup.wire.ProtoAdapter#SINT32"
)
public final Integer psychologicalAge;
@WireField(
tag = 11,
adapter = "PetPb#ADAPTER"
)
public final PetPb pet;
@WireField(
tag = 12,
adapter = "HousePb#ADAPTER",
label = WireField.Label.REPEATED
)
public final List<HousePb> ownHouses;
@WireField(
tag = 13,
keyAdapter = "com.squareup.wire.ProtoAdapter#STRING",
adapter = "ClothesPb#ADAPTER"
)
public final Map<String, ClothesPb> wardrobes;
...
}
...
typewriter将它翻译成:
public class UserPbModel extends TypewriterBaseModel implements Serializable {
public String objectId;
public final String name;
public final String favouriteSport;
public final String favouriteMovie;
public final boolean hasMarried;
public final EducationLevel education;
public final int age;
public final int psychologicalAge;
public final PetPbModel pet;
public final List<HousePbModel> houses;
public final Map<String, ClothesPbModel> wardrobes;
@SuppressWarnings("unchecked")
public UserPbModel(UserPb prototype, String objectId) {
this.objectId = objectId;
this.name = prototype.userName;
this.favouriteSport = prototype.favouriteSport;
this.favouriteMovie = prototype.favouriteMovie;
this.hasMarried = prototype.hasMarried;
this.age = prototype.age;
this.psychologicalAge = prototype.psychologicalAge;
this.education = EducationLevel.fromJSONString(prototype.educationEnum);
this.pet = (PetPbModel)transformModelFromPrototype(prototype.pet);
this.houses = (List<HousePbModel>)transformModelFromPrototype(prototype.ownHouses);
this.wardrobes = (Map<String, ClothesPbModel>)transformModelFromPrototype(prototype.wardrobes);
UserPbModel.unidirectionalDataflow(this, this.objectId);
}
public Object transformModelFromPrototype(Object prototype) {
if (prototype == null) {
return null;
}
if (prototype instanceof ClothesPb) {
return new ClothesPbModel((ClothesPb)prototype, this.objectId);
}
if (prototype instanceof HousePb) {
return new HousePbModel((HousePb)prototype);
}
if (prototype instanceof PetPb) {
return new PetPbModel((PetPb)prototype);
}
return super.transformModelFromPrototype(prototype);
}
public UserPbModel(String objectId,
String name,
String favouriteSport,
String favouriteMovie,
boolean hasMarried,
EducationLevel education,
int age,
int psychologicalAge,
PetPbModel pet,
List<HousePbModel> houses,
Map<String, ClothesPbModel> wardrobes) {
this.objectId = objectId;
this.name = name;
this.favouriteSport = favouriteSport;
this.favouriteMovie = favouriteMovie;
this.hasMarried = hasMarried;
this.education = education;
this.age = age;
this.psychologicalAge = psychologicalAge;
this.pet = pet;
this.houses = houses;
this.wardrobes = wardrobes;
UserPbModel.unidirectionalDataflow(this, this.objectId);
}
public Builder builder() {
Builder builder = new Builder();
builder.objectId = objectId;
builder.name = name;
builder.favouriteSport = favouriteSport;
builder.favouriteMovie = favouriteMovie;
builder.hasMarried = hasMarried;
builder.education = education;
builder.age = age;
builder.psychologicalAge = psychologicalAge;
builder.pet = pet;
builder.houses = houses;
builder.wardrobes = wardrobes;
return builder;
}
public static void unidirectionalDataflow(UserPbModel model, String objectId) {
// unidirectional data flow
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (!(obj instanceof UserPbModel)) return false;
UserPbModel other = (UserPbModel) obj;
return (objectId != null ? objectId.equals(other.objectId) : other.objectId == null)
&& (name != null ? name.equals(other.name) : other.name == null)
&& (favouriteSport != null ? favouriteSport.equals(other.favouriteSport) : other.favouriteSport == null)
&& (favouriteMovie != null ? favouriteMovie.equals(other.favouriteMovie) : other.favouriteMovie == null)
&& Boolean.compare(hasMarried, other.hasMarried) == 1
&& (education != null ? education.equals(other.education) : other.education == null)
&& Integer.compare(age, other.age) == 1
&& Integer.compare(psychologicalAge, other.psychologicalAge) == 1
&& (pet != null ? pet.equals(other.pet) : other.pet == null)
&& (houses != null ? houses.equals(other.houses) : other.houses == null)
&& (wardrobes != null ? wardrobes.equals(other.wardrobes) : other.wardrobes == null);
}
@Override
public int hashCode() {
int result = super.hashCode() != 0 ? super.hashCode() : 1;
result = result * 37 + (objectId != null ? objectId.hashCode() : 0);
result = result * 37 + (name != null ? name.hashCode() : 0);
result = result * 37 + (favouriteSport != null ? favouriteSport.hashCode() : 0);
result = result * 37 + (favouriteMovie != null ? favouriteMovie.hashCode() : 0);
result = result * 37 + Boolean.valueOf(hasMarried).hashCode();
result = result * 37 + (education != null ? education.hashCode() : 0);
result = result * 37 + Integer.valueOf(age).hashCode();
result = result * 37 + Integer.valueOf(psychologicalAge).hashCode();
result = result * 37 + (pet != null ? pet.hashCode() : 0);
result = result * 37 + (houses != null ? houses.hashCode() : 0);
result = result * 37 + (wardrobes != null ? wardrobes.hashCode() : 0);
return result;
}
public class Builder {
public String objectId;
public String name;
public String favouriteSport;
public String favouriteMovie;
public boolean hasMarried;
public EducationLevel education;
public int age;
public int psychologicalAge;
public PetPbModel pet;
public List<HousePbModel> houses;
public Map<String, ClothesPbModel> wardrobes;
public Builder objectId(String objectId) {
this.objectId = objectId;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder favouriteSport(String favouriteSport) {
this.favouriteSport = favouriteSport;
return this;
}
public Builder favouriteMovie(String favouriteMovie) {
this.favouriteMovie = favouriteMovie;
return this;
}
public Builder hasMarried(boolean hasMarried) {
this.hasMarried = hasMarried;
return this;
}
public Builder education(EducationLevel education) {
this.education = education;
return this;
}
public Builder age(int age) {
this.age = age;
return this;
}
public Builder psychologicalAge(int psychologicalAge) {
this.psychologicalAge = psychologicalAge;
return this;
}
public Builder pet(PetPbModel pet) {
this.pet = pet;
return this;
}
public Builder houses(List<HousePbModel> houses) {
this.houses = houses;
return this;
}
public Builder wardrobes(Map<String, ClothesPbModel> wardrobes) {
this.wardrobes = wardrobes;
return this;
}
public UserPbModel build() {
return new UserPbModel(objectId,
name,
favouriteSport,
favouriteMovie,
hasMarried,
education,
age,
psychologicalAge,
pet,
houses,
wardrobes);
}
}
}