针对Codable:实现在swift中像js那样使用JSON和codiceswift这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展Android通过onDraw实现在View中绘图操作、C
针对Codable: 实现在 swift 中像 js 那样使用 JSON和codice swift这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展Android 通过 onDraw 实现在 View 中绘图操作、Codable - 更好的使用 code 字段、ios – Swift:Codable – 提取单个编码密钥、java 集成 pageoffice 实现在 word 中插入表格并赋值等相关知识,希望可以帮助到你。
本文目录一览:- Codable: 实现在 swift 中像 js 那样使用 JSON(codice swift)
- Android 通过 onDraw 实现在 View 中绘图操作
- Codable - 更好的使用 code 字段
- ios – Swift:Codable – 提取单个编码密钥
- java 集成 pageoffice 实现在 word 中插入表格并赋值
Codable: 实现在 swift 中像 js 那样使用 JSON(codice swift)
Codable: 实现在 swift 中像 js 那样使用 JSON
官方文档,关于 Codable 实现:https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types
像 js
一样,iOS 11
之后,swift
也可以方便的使用 json
来传递数据了。
要想使用 json
, 你操作的类需要实现 Codable
接口Foundation
中的所有类都已经实现了 Cadable
,所以如果你的实体中没有自定义的一些数据类型,都可以直接使用 JSON
如 js
一样,swift
中的 json
也有:
-
JSONEncoder
将数据转成json
数据 -
JOSNDecoder
将json
数据,转为可用的你需要的数据类型
看下面的 PlayGround
例子便知道如何使用了
由对象转字符串
import Foundation
struct Person: Codable {
var name: String
var age: Int
var intro: String
}
let kyle = Person(name: "Kyle", age: 29, intro: "A web developer")
let tina = Person(name: "Tina", age: 26, intro: "A teacher for English")
let persons = [kyle, tina]
// Encode
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted // setup formatter
let jsonData = try encoder.encode(persons)
print(String(data: jsonData, encoding: .utf8)!)
// Decode
let decoder = JSONDecoder()
// 注意 decode() 中的第一个参数
let people = try decoder.decode(Array<Person>.self, from: jsonData)
print(people[0].name)
输出如下:
[
{
"name" : "Kyle",
"age" : 29,
"intro" : "A web developer"
},
{
"name" : "Tina",
"age" : 26,
"intro" : "A teacher for English"
}
]
Kyle
由字符串转对象
import Foundation
struct Person: Codable {
let name: String
let age: Int
let intro: String
}
let jsonString = """
[
{
"name": "Kyle",
"age": 27,
"intro": "A font-end enginer",
"location": "Jinan"
},
{
"name": "Tina",
"age": 26,
"intro": "A UI enginer",
"location": "Jinan"
}
]
"""
// 1. 先从字符串转为 Data
let jsonData = jsonString.data(using: .utf8)!
// 2. 再用 Data 转成对应的对象
let decoder = JSONDecoder()
let persons = try decoder.decode(Array<Person>.self, from: jsonData)
print(type(of: persons[0]))
对象名与 json 名不一致时
有些时候,对象声明中的变量名跟json中的键名不一致,如 nameEn
在 json 中需要为 json_en
只需要在对象声明中用 CodingKeys
声明要转成的字符串即可,如下:不需要转的就不需要写 =
后面的东西了
//
// Person.swift
// CustomisedViews
//
// Created by Kyle on 2020/3/2.
// Copyright © 2020 KyleBing. All rights reserved.
//
import Foundation
struct Person: Codable {
var id: String
var name: String
var nameEn: String
var nickName: String
var perk: String
var motto: String
var health: String
var sanity: String
var hunger: String
var version: String
var pic: String
enum CodingKeys: String, CodingKey {
case nameEn = "name_en"
case nickName = "nick_name"
// 下面这些变量名不需要变,就只写 case 就可以了
// 要把对象中的变量全部遍历出来,不然会出错
case id
case name
case perk
case motto
case health
case sanity
case hunger
case version
case pic
}
}
Android 通过 onDraw 实现在 View 中绘图操作
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="@+id/layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
></LinearLayout>
</RelativeLayout>
package com.example.zidingyi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
public class DrawView extends View {
float paintX =400;
float paintY =600;
public DrawView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
/**
* 这个方法会在初始化后背调用一次,invaildate () 的时候会被调用
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint=new Paint ();// 设置一个笔
paint.setAntiAlias (true);// 设置没有锯齿
paint.setColor (Color.RED);// 设置笔的颜色
canvas.drawCircle (paintX, paintY, 50, paint);// 距离画圆
}
}
package com.example.zidingyi;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.LinearLayout;
import android.widget.Toast;
public class MainActivity extends Activity {
private LinearLayout layout;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layout = (LinearLayout) findViewById (R.id.layout);// 找到这个空间
final DrawView drawView = new DrawView (this);// 创建自定义的控件
drawView.setMinimumHeight(300);
drawView.setMinimumWidth(500);
layout.addView (drawView);// 讲自定义的控件进行添加
// 设置一个触摸事件
drawView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// 改变之前的 X,Y
drawView.paintX=event.getX();
drawView.paintY=event.getY();
// 调用重新绘制
drawView.invalidate();
return true;
}
});
}
}
Codable - 更好的使用 code 字段
ios – Swift:Codable – 提取单个编码密钥
let value = try! decoder.decode([String:Applmusic].self,from: $0["applmusic"])
这成功处理了以下JSON:
{ "applmusic":{ "code":"AAPL","quality":"good","line":"She told me don't worry",}
但是,无法使用以下代码中的applmusic编码密钥提取JSON:
{ "applmusic":{ "code":"AAPL",},"spotify":{ "differentcode":"SPOT","music_quality":"good","spotify_specific_code":"absent in apple" },"amazon":{ "amzncode":"SPOT","stanley":"absent in apple" } }
applmusic,spotify和amazon的数据模型是不同的.但是,我只需要提取applmusic并省略其他编码密钥.
我的Swift数据模型如下:
public struct Applmusic: Codable { public let code: String public let quality: String public let line: String }
API以完整的JSON响应,我不能要求它只给我所需的字段.
如何只解码json的特定部分?看来,Decodable要求我先对整个json进行反序列化,所以我必须知道它的完整数据模型.
显然,其中一个解决方案是创建一个单独的Response模型,只是为了包含applmusicparameter,但它看起来像一个hack:
public struct Response: Codable { public struct Applmusic: Codable { public let code: String public let quality: String public let line: String } // The only parameter is `applmusic`,ignoring the other parts - works fine public let applmusic: Applmusic }
你能提出一个更好的方法来处理这样的JSON结构吗?
多一点洞察力
我在通用扩展中使用了以下技术,它为我自动解码API响应.因此,我更倾向于概括一种处理此类情况的方法,而无需创建根结构.如果我需要的密钥在JSON结构中是3层深度怎么办?
这是为我解码的扩展:
extension Endpoint where Response: Swift.Decodable { convenience init(method: Method = .get,path: Path,codingKey: String? = nil,parameters: Parameters? = nil) { self.init(method: method,path: path,parameters: parameters,codingKey: codingKey) { if let key = codingKey { guard let value = try decoder.decode([String:Response].self,from: $0)[key] else { throw RestClientError.valueNotFound(codingKey: key) } return value } return try decoder.decode(Response.self,from: $0) } } }
API的定义如下:
extension API { static func getMusic() -> Endpoint<[Applmusic]> { return Endpoint(method: .get,path: "/api/music",codingKey: "applmusic") } }
解决方法
你可以像这样使用它:
let post = try decoder.decode(Post.self,from: data,keyPath: "nested.post")
您可以创建一个Decodable包装器(例如,ModelResponse),并将所有逻辑用于提取嵌套模型,其中包含一个键:
struct DecodingHelper { /// Dynamic key private struct Key: CodingKey { let stringValue: String init?(stringValue: String) { self.stringValue = stringValue self.intValue = nil } let intValue: Int? init?(intValue: Int) { return nil } } /// Dummy model that handles model extracting logic from a key private struct ModelResponse<nestedModel: Decodable>: Decodable { let nested: nestedModel public init(from decoder: Decoder) throws { let key = Key(stringValue: decoder.userInfo[CodingUserInfoKey(rawValue: "my_model_key")!]! as! String)! let values = try decoder.container(keyedBy: Key.self) nested = try values.decode(nestedModel.self,forKey: key) } } static func decode<T: Decodable>(modelType: T.Type,fromKey key: String) throws -> T { // mock data,replace with network response let path = Bundle.main.path(forResource: "test",ofType: "json")! let data = try Data(contentsOf: URL(fileURLWithPath: path),options: .mappedIfSafe) let decoder = JSONDecoder() // ***Pass in our key through `userInfo` decoder.userInfo[CodingUserInfoKey(rawValue: "my_model_key")!] = key let model = try decoder.decode(ModelResponse<T>.self,from: data).nested return model } }
您可以通过JSONDecoder的userInfo(“my_model_key”)传递所需的密钥.然后将其转换为ModelResponse中的动态Key以实际提取模型.
然后你可以像这样使用它:
let appl = try DecodingHelper.decode(modelType: Applmusic.self,fromKey: "applmusic") let amazon = try DecodingHelper.decode(modelType: Amazon.self,fromKey: "amazon") let spotify = try DecodingHelper.decode(modelType: Spotify.self,fromKey: "spotify") print(appl,amazon,spotify)
完整代码:
https://gist.github.com/aunnnn/2d6bb20b9dfab41189a2411247d04904
额外奖励:深层嵌套密钥
在玩了更多之后,我发现你可以使用这个修改过的ModelResponse轻松解码任意深度的键:
private struct ModelResponse<nestedModel: Decodable>: Decodable { let nested: nestedModel public init(from decoder: Decoder) throws { // Split nested paths with '.' var keypaths = (decoder.userInfo[CodingUserInfoKey(rawValue: "my_model_key")!]! as! String).split(separator: ".") // Get last key to extract in the end let lastKey = String(keypaths.popLast()!) // Loop getting container until reach final one var targetContainer = try decoder.container(keyedBy: Key.self) for k in keypaths { let key = Key(stringValue: String(k))! targetContainer = try targetContainer.nestedContainer(keyedBy: Key.self,forKey: key) } nested = try targetContainer.decode(nestedModel.self,forKey: Key(stringValue: lastKey)!) }
然后你可以像这样使用它:
let deeplynestedModel = try DecodingHelper.decode(modelType: Amazon.self,fromKey: "nest1.nest2.nest3")
从这个json:
{ "apple": { ... },"amazon": { "amzncode": "SPOT","music_quality": "good","stanley": "absent in apple" },"nest1": { "nest2": { "amzncode": "nest works","music_quality": "Great","stanley": "Oh yes","nest3": { "amzncode": "nest works,again!!!","stanley": "Oh yes" } } } }
完整代码:https://gist.github.com/aunnnn/9a6b4608ae49fe1594dbcabd9e607834
java 集成 pageoffice 实现在 word 中插入表格并赋值
Word中的table操作需要借助数据区域(DataRegion)实现的,要求数据区域完整的包含了整个Table的内容,这样才可以通过数据区域控制和操作table。因此,要想使用table,则必须在word文件中插入书签。而table的插入,既可以在Word模版中书签处手动插入:工具栏“插入”→“表格”,亦可以在程序中通过数据区域动态添加。
下面介绍一下动态添加表格的具体步骤
1:给Word模板中创建一个书签。(两种方法)
(1)可以在word 模板中手动添加一个书签:工具栏“插入”→“书签”
(2)用 pageoffice 动态创建一个数据区域(书签)
2:插入表格
2:具体的代码
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ page
import="com.zhuozhengsoft.pageoffice.*,com.zhuozhengsoft.pageoffice.wordwriter.*"%>
<%
PageOfficeCtrl poCtrl = new PageOfficeCtrl(request);
WordDocument doc = new WordDocument();
//在word中指定的"PO_table1"的数据区域内动态创建一个3行5列的表格
Table table1 = doc.openDataRegion("PO_table").createTable(3,5,WdAutoFitBehavior.wdAutoFitWindow);
//合并(1,1)到(3,1)的单元格并赋值
table1.openCellRC(1,1).mergeTo(3,1);
table1.openCellRC(1,1).setValue("合并后的单元格");
//给表格table1中剩余的单元格赋值
for(int i=1;i<4;i++){
table1.openCellRC(i, 2).setValue("AA" + String.valueOf(i));
table1.openCellRC(i, 3).setValue("BB" + String.valueOf(i));
table1.openCellRC(i, 4).setValue("CC" + String.valueOf(i));
table1.openCellRC(i, 5).setValue("DD" + String.valueOf(i));
}
//在"PO_table1"后面动态创建一个新的数据区域"PO_table2",用于创建新的一个5行5列的表格table2
DataRegion drTable2= doc.createDataRegion("PO_table2", DataRegionInsertType.After, "PO_table1");
Table table2=drTable2.createTable(5,5,WdAutoFitBehavior.wdAutoFitWindow);
//给新表格table2赋值
for(int i=1;i<6;i++){
table2.openCellRC(i, 1).setValue("AA" + String.valueOf(i));
table2.openCellRC(i, 2).setValue("BB" + String.valueOf(i));
table2.openCellRC(i, 3).setValue("CC" + String.valueOf(i));
table2.openCellRC(i, 4).setValue("DD" + String.valueOf(i));
table2.openCellRC(i, 5).setValue("EE" + String.valueOf(i));
}
poCtrl.setWriter(doc);//此行必须
poCtrl.setServerPage(request.getContextPath()+"/poserver.zz");
poCtrl.webOpen("doc/createTable.doc", OpenModeType.docNormalEdit,"张佚名");
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Word中动态创建表格</title>
</head>
<body>
<div>
<%=poCtrl.getHtmlCode("PageOfficeCtrl1")%>
</div>
</body>
</html>
最终效果
大家可以去pageoffice官网下载示例代码直接将samples4文件夹扔到Tomcat的webapps下,启动Tomcat,浏览器访问。
刚开始接触pageoffice的话,也可以看视频快速上手http://www.zhuozhengsoft.com/Technical/
关于Codable: 实现在 swift 中像 js 那样使用 JSON和codice swift的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于Android 通过 onDraw 实现在 View 中绘图操作、Codable - 更好的使用 code 字段、ios – Swift:Codable – 提取单个编码密钥、java 集成 pageoffice 实现在 word 中插入表格并赋值的相关信息,请在本站寻找。
本文标签: