java-codable is a Java beans to swift codable converter, it is java compile plugin, you need to add this your maven configuration to get it working.
Add codeable to project dependencies
<dependency>
<groupId>io.github.pakistancan</groupId>
<artifactId>codable-converter</artifactId>
<version>1.0.2</version>
</dependency>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessors>
<annotationProcessor>io.github.pakistancan.codable.processor.CodableGenerator</annotationProcessor>
</annotationProcessors>
<verbose>true</verbose>
<compilerArguments>
<Xlint />
<AOutputDir>./generated/</AOutputDir>
<APackagePrefix>com.alix.</APackagePrefix>
<AClassModifier>open</AClassModifier>
<!-- -Xlint:all -->
</compilerArguments>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
</plugins>
</build>
It will convert classes referenced from com.alix.
and all of its sub-packages, output will be generated in <PROJECT_DIR>/generated/swift
, if package contains .request.
then it'll generate those classes in REQ subfolder, otherwise in RES sub-folder.
Enums will be generated in Enums
sub-folder, if there is any date referenced in any class, Formatters class will be generated in Formatter/
sub-folder
If you are using gradle, it should be as simple as adding anootation processor to dependencies section of your build.gradle file
annotationProcessor 'io.github.pakistancan:codable-converter:1.0.3'
compiler arguments can be configured using
compileJava {
options.compilerArgs += '-AClassModifier=public'
}
Decorate your beans with @Codable annotation, if it is specified on base class it is already applied on derived classes, java-codable regards com.fasterxml.jackson.annotation.JsonProperty
to apply custom name to serialize/deserialize properties and com.fasterxml.jackson.annotation.JsonFormat
to use specific date formats.
/**
*
*/
package com.alix.request;
import io.github.pakistancan.codable.annotation.Codable;
import io.github.pakistancan.codable.annotation.IgnoreProperty;
/**
* @author muhammadali
*
*/
@Codable
public class BookInfo {
private String title;
private String isbn;
private AuthorInfo[] authors;
@IgnoreProperty
private String ignoredField;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public AuthorInfo[] getAuthors() {
return authors;
}
public void setAuthors(AuthorInfo[] authors) {
this.authors = authors;
}
}
and
package com.alix.request;
public class AuthorInfo {
private String author;
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
It'll generate swift files for both value objects.
Output files for the above classes looks like
BookInfo.swift
import Foundation
public class BookInfo: Codable {
public init() {
}
public var title: String = ""
public var isbn: String = ""
public var authors: [AuthorInfo] = []
private enum CodingKeys: String, CodingKey {
case isbn = "isbn"
case title = "title"
case authors = "authors"
}
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let title = try container.decodeIfPresent(String.self, forKey: .title) {
self.title = title
}
if let isbn = try container.decodeIfPresent(String.self, forKey: .isbn) {
self.isbn = isbn
}
if let authors = try container.decodeIfPresent([AuthorInfo].self, forKey: .authors) {
self.authors = authors
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(self.title, forKey: .title)
try container.encodeIfPresent(self.isbn, forKey: .isbn)
try container.encodeIfPresent(self.authors, forKey: .authors)
}
}
AuthorInfo.swift
import Foundation
public class AuthorInfo: Codable {
public init() {
}
public var author: String = ""
private enum CodingKeys: String, CodingKey {
case author = "author"
}
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let author = try container.decodeIfPresent(String.self, forKey: .author) {
self.author = author
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(self.author, forKey: .author)
}
}
All primitive classes, user defined classes and collection classes are supported(except queues), here is another example you can use to get a better overview
package com.alix.request;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.github.pakistancan.codable.annotation.Codable;
@Codable
public class Sample {
@JsonProperty("sample_id")
public int id;
@JsonProperty("sample_list")
public List<String> sampleList;
@JsonProperty("sample_list1")
public ArrayList<String> sampleList1;
@JsonProperty("sample_set")
public Set<String> sampleSet;
@JsonProperty("sample_list_set")
public Set<List<String>> sampleListSet;
public HashSet<String> sampleHashSet;
public TreeSet<String> sampleTreeSet;
public LinkedHashSet<String> linkedHashSet;
public HashMap<String, String> sampleHashMap;
public TreeMap<String, String> sampleTreeMap;
public LinkedHashMap<String, Set<String>> linkedHashMap;
public LinkedHashMap<String, TreeSet<String>> linkedHashMapSet;
public String[] inputs;
public String[][] inputsMap;
}
Output of above class should be something like this
Sample.swift
import Foundation
public class Sample: Codable {
public init() {
}
public var id: Int = 0
public var sampleList: [String] = []
public var sampleList1: [String] = []
public var sampleSet: [String] = []
public var sampleListSet: [[String]] = []
public var sampleHashSet: [String] = []
public var sampleTreeSet: [String] = []
public var linkedHashSet: [String] = []
public var sampleHashMap: [String:String] = [:]
public var sampleTreeMap: [String:String] = [:]
public var linkedHashMap: [String:[String]] = [:]
public var linkedHashMapSet: [String:[String]] = [:]
public var inputs: [String] = []
public var inputsMap: [[String]] = []
private enum CodingKeys: String, CodingKey {
case linkedHashSet = "linkedHashSet"
case sampleTreeMap = "sampleTreeMap"
case sampleHashSet = "sampleHashSet"
case inputs = "inputs"
case sampleListSet = "sample_list_set"
case sampleHashMap = "sampleHashMap"
case sampleList = "sample_list"
case sampleSet = "sample_set"
case linkedHashMap = "linkedHashMap"
case sampleTreeSet = "sampleTreeSet"
case linkedHashMapSet = "linkedHashMapSet"
case sampleList1 = "sample_list1"
case inputsMap = "inputsMap"
case id = "sample_id"
}
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if let id = try container.decodeIfPresent(Int.self, forKey: .id) {
self.id = id
}
if let sampleList = try container.decodeIfPresent([String].self, forKey: .sampleList) {
self.sampleList = sampleList
}
if let sampleList1 = try container.decodeIfPresent([String].self, forKey: .sampleList1) {
self.sampleList1 = sampleList1
}
if let sampleSet = try container.decodeIfPresent([String].self, forKey: .sampleSet) {
self.sampleSet = sampleSet
}
if let sampleListSet = try container.decodeIfPresent([[String]].self, forKey: .sampleListSet) {
self.sampleListSet = sampleListSet
}
if let sampleHashSet = try container.decodeIfPresent([String].self, forKey: .sampleHashSet) {
self.sampleHashSet = sampleHashSet
}
if let sampleTreeSet = try container.decodeIfPresent([String].self, forKey: .sampleTreeSet) {
self.sampleTreeSet = sampleTreeSet
}
if let linkedHashSet = try container.decodeIfPresent([String].self, forKey: .linkedHashSet) {
self.linkedHashSet = linkedHashSet
}
if let sampleHashMap = try container.decodeIfPresent([String:String].self, forKey: .sampleHashMap) {
self.sampleHashMap = sampleHashMap
}
if let sampleTreeMap = try container.decodeIfPresent([String:String].self, forKey: .sampleTreeMap) {
self.sampleTreeMap = sampleTreeMap
}
if let linkedHashMap = try container.decodeIfPresent([String:[String]].self, forKey: .linkedHashMap) {
self.linkedHashMap = linkedHashMap
}
if let linkedHashMapSet = try container.decodeIfPresent([String:[String]].self, forKey: .linkedHashMapSet) {
self.linkedHashMapSet = linkedHashMapSet
}
if let inputs = try container.decodeIfPresent([String].self, forKey: .inputs) {
self.inputs = inputs
}
if let inputsMap = try container.decodeIfPresent([[String]].self, forKey: .inputsMap) {
self.inputsMap = inputsMap
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(self.id, forKey: .id)
try container.encodeIfPresent(self.sampleList, forKey: .sampleList)
try container.encodeIfPresent(self.sampleList1, forKey: .sampleList1)
try container.encodeIfPresent(self.sampleSet, forKey: .sampleSet)
try container.encodeIfPresent(self.sampleListSet, forKey: .sampleListSet)
try container.encodeIfPresent(self.sampleHashSet, forKey: .sampleHashSet)
try container.encodeIfPresent(self.sampleTreeSet, forKey: .sampleTreeSet)
try container.encodeIfPresent(self.linkedHashSet, forKey: .linkedHashSet)
try container.encodeIfPresent(self.sampleHashMap, forKey: .sampleHashMap)
try container.encodeIfPresent(self.sampleTreeMap, forKey: .sampleTreeMap)
try container.encodeIfPresent(self.linkedHashMap, forKey: .linkedHashMap)
try container.encodeIfPresent(self.linkedHashMapSet, forKey: .linkedHashMapSet)
try container.encodeIfPresent(self.inputs, forKey: .inputs)
try container.encodeIfPresent(self.inputsMap, forKey: .inputsMap)
}
}
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. Please have a look at CONTRIBUTING