import os import logging import logging.handlers from flask import Flask, g, request, json app = Flask(__name__) #[ Log 配置 ]############################################################# # 用來記錄無法處理的錯誤 (PS: 使用 WSGI 會依附 Apache 的設定,可以不用配置) # https://docs.python.org/zh-cn/3/library/logging.html formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s") # https://docs.python.org/zh-tw/3/library/logging.handlers.html#timedrotatingfilehandler handler = logging.handlers.TimedRotatingFileHandler("log/web-api", when = "D", interval = 1, backupCount = 7, encoding = "UTF-8", delay = False, utc = True) handler.setFormatter(formatter) app.logger.addHandler(handler)
2023-02-21 10:33
[Python] Flask Log 配置
2023-02-21 10:13
[Python] Flask 自訂日期的 Json 轉換
import os import datetime import time from flask import Flask, g, request, json from flask.json import JSONEncoder class CustomJsonEncoder(JSONEncoder): # 針對日期自訂 Json 轉換 def default(self, obj): if isinstance(obj, datetime.date): return obj.isoformat().replace('T', ' ') return super().default(obj) app = Flask(__name__) app.json_encoder = CustomJsonEncoder app.config['JSON_AS_ASCII'] = False # 返回結果可以正確顯示中文
2023-02-21 10:05
[Python] Flask MySQL 連線管理
import os import mysql.connector as sql from werkzeug.exceptions import HTTPException, BadRequest from flask import Flask, g, request, json app = Flask(__name__) #[ DB 處裡 ]############################################################# # https://docsxyz.com/zh-hant/wiki/python/connector-python-connectargs db_config = { 'host' : "localhost", 'user' : "XXXX", 'passwd' : "XXXX", 'db' : 'XXXX', 'use_pure' : True, 'autocommit': True, 'charset' : 'utf8', } @app.before_request def before_request(): # 在 request 前開啟 DB 連線 # g 是 Flask global 在每個 request 有獨立的 context g.cnt = sql.connect(**db_config) g.cursor = g.cnt.cursor(dictionary = True) @app.after_request def after_request(response): # 在 request 後結束 DB 連線 cursor = g.get('cursor', None) if cursor is not None: # 當 cursor 還有 row 沒有取出,close 會發生錯誤 if cursor.with_rows : cursor.fetchall() cursor.close() cnt = g.get('cnt', None) if cnt is not None: cnt.close() return response
2023-02-21 09:55
[Python] Flask 筆記
相依套件:
-------------------------------------------------------------------------------
python-3.8.10-amd64.exe
pip install Flask
pip install flask_cors
pip install mysql-connector-python
pip install pycryptodomex
pip install py-linq # https://viralogic.github.io/py-enumerable/
Apache CGI 配置,用虛擬 Script 指向到 app.cgi
-------------------------------------------------------------------------------
ScriptAlias /web-api D:/iog-project/web-api/app.cgi
<Directory "D:/iog-project/web-api/">
Options ExecCGI
AllowOverride all
Require local
</Directory>
-------------------------------------------------------------------------------
# 正常執行
flask run
# 除錯執行 (flask 會提供除錯功能,並將 logger 從 warning 提升到 debug
export FLASK_ENV=development # for linux / git bash
set FLASK_ENV=development # for windows cmd
flask run
# 列出設定的路徑
flask routes
其他
-------------------------------------------------------------------------------
因為 web-api 的格式是 Json,所以遵照 JS 的命名風格,欄位名稱開頭小寫第二個字大寫
2023-02-21 09:53
[Python] Flask 錯誤處裡
from werkzeug.exceptions import HTTPException, BadRequest from flask import Flask, g, request, json app = Flask(__name__) #[ 錯誤處裡 ]############################################################# @app.errorhandler(Exception) def handle_exception(e): if isinstance(e, HTTPException): return e # 讓 HTTPException 交由下一個處理 app.logger.exception("Internal Server Error.") # log 錯誤訊息 if app.debug : return e return json.jsonify({'message': 'Internal Server Error.'}), 500 @app.errorhandler(HTTPException) def handle_exception(e): response = e.get_response() return json.jsonify({'message': e.description}), e.code
2019-07-22 16:49
C# COM 元件使用 MTA
先前有用到一個通訊用的 COM 元件,因為連線不穩的時候會影響到 Main Thread 造成這個 WinForm UI 卡住,連帶所有 Main Thread 下的其他 Thread 都卡住,最先找到的方法是在 Program Main 上改用 MTAThreadAttribute,的確是可以解決卡住的問題。
但 WPF 就不可以用 MTAThreadAttribute,因為 WPF 必須執行在 STAThread 的環境上,又開始苦惱這個問題了,問題應該還是有解套的辦法的只是知識不足,最後在 WIKI 中看到重要的知識。
WIKI 元件物件模型
所以只要用其他 Thread 去建立 COM 元件就不會影響到 Main Thread 了,簡單的解決問題,果然是知識不足。
但 WPF 就不可以用 MTAThreadAttribute,因為 WPF 必須執行在 STAThread 的環境上,又開始苦惱這個問題了,問題應該還是有解套的辦法的只是知識不足,最後在 WIKI 中看到重要的知識。
WIKI 元件物件模型
一個COM物件只能存在於一個套間。COM物件一經建立就確定所屬套間,並且直到銷毀它一直存在於這個套間。
所以只要用其他 Thread 去建立 COM 元件就不會影響到 Main Thread 了,簡單的解決問題,果然是知識不足。
ActEasyIF actConnection; var waiter = new AutoResetEvent(false); new Thread(() => { /* 建構 COM 元件 */ _actConnection = new ActEasyIF(); waiter.Set(); }).Start(); waiter.WaitOne(500); /* 等待建立結束 */
2019-07-22 15:36
C# struct 轉換到 byte array
StructLayout: https://docs.microsoft.com/zh-tw/dotnet/api/system.runtime.interopservices.layoutkind?view=netframework-4.8
Pack: 資料欄位的對齊,這會影響最短欄位的 byte 長度
Pack: 資料欄位的對齊,這會影響最短欄位的 byte 長度
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct PollResponse { public int AppId; public byte Serial; public short Station; } void Main() { var data = new PollResponse { AppId = 1, Serial = 2, Station = 3, }; Type type = typeof(PollResponse); int size = Marshal.SizeOf(type); var bytes = new byte[size]; /* struct to byte array */ IntPtr ptrIn = Marshal.AllocHGlobal(size); Marshal.StructureToPtr(data, ptrIn, true); Marshal.Copy(ptrIn, bytes, 0, size); Marshal.FreeHGlobal(ptrIn); BitConverter.ToString(bytes).Dump(); /* 01-00-00-00 - 02 - 03-00 */ /* byte array to struct */ IntPtr ptrOut = Marshal.AllocHGlobal(size); Marshal.Copy(bytes, 0, ptrOut, size); var result = (PollResponse)Marshal.PtrToStructure(ptrOut, type); Marshal.FreeHGlobal(ptrOut); result.Dump(); /* { AppId = 1, Serial = 2, Station = 3 } */ }
2019-07-21 17:21
C# 讓 Dequeue 更方便的擴充方法
void Main() { var queue = new Queue<int>(); for (int i = 0; i < 10; i++) { queue.Enqueue(i); } string.Join(",", queue).Dump(); /* 0,1,2,3,4,5,6,7,8,9 */ var take = queue.EnumerateDequeue().Take(4).ToList(); string.Join(",", take).Dump(); /* 0,1,2,3 */ string.Join(",", queue).Dump(); /* 4,5,6,7,8,9 */ var take2 = queue.EnumerateDequeue().Take(40).ToList(); string.Join(",", take2).Dump(); /* 4,5,6,7,8,9 */ string.Join(",", queue).Dump(); /* */ } public static class QueueExtensions { public static IEnumerable<T> EnumerateDequeue<T>(this Queue<T> source) { while (source.Count > 0) { yield return source.Dequeue(); } } public static IEnumerable<T> EnumerateDequeue<T>(this ConcurrentQueue<T> source) { T outValue; while (source.TryDequeue(out outValue)) { yield return outValue; } } }
2019-07-21 17:06
C# 在 Enum 上增加附加資訊
C# 的 Enum 是個很方便的類型,如果可以再增加額外的資訊就更方便了,這裡利用 Attribute 去定義 Enum 額外的資訊,再用擴充方法取得 Enum 所屬的資訊。
用 Attribute 來定義有個好處,未來在增減 Enum 時可以一起進行修改,不用擔心會有遺漏而沒修改的問題。
用 Attribute 來定義有個好處,未來在增減 Enum 時可以一起進行修改,不用擔心會有遺漏而沒修改的問題。
void Main() { PortAreaCode.F1Front.GetFloor().Dump(); /* F1 */ } public enum PortAreaCode { [AreaMeta("None", 0)] None, [AreaMeta("F1", 1)] F1Front, [AreaMeta("F2", 1)] F2Front, } /// <summary>PortAreaCode 額外附屬資訊定義的 Attribute</summary> [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)] class AreaMetaAttribute : Attribute { public string Floor { get; private set; } public int WarehouseId { get; private set; } public AreaMetaAttribute() : this("None", 0) { } public AreaMetaAttribute(string floor, int warehouseId) { Floor = floor; WarehouseId = warehouseId; } } /// <summary>PortAreaCode 的擴充方法</summary> public static class PortAreaCodeExtensions { private static AreaMetaAttribute _defaultMeta = new AreaMetaAttribute(); private static AreaMetaAttribute getMeta(PortAreaCode value) { FieldInfo field = typeof(PortAreaCode).GetField(value.ToString()); if(field == null) { return _defaultMeta; } var meta = field.GetCustomAttribute<AreaMetaAttribute>(); return meta ?? _defaultMeta; } public static string GetFloor(this PortAreaCode value) { return getMeta(value).Floor; } public static int GetWarehouseId(this PortAreaCode value) { return getMeta(value).WarehouseId; } }
2019-07-21 16:29
C# 用 gzip 壓縮字串並取得 base64 字串
這個使用方式的效果是有但書的,當 Source 的重複率不高壓縮的效果就不會好,再加上 base64 就是用可見文字去表示 byte 值,這會讓 base64 後的結果比 byte array 還要長,所以壓縮率沒有到達一定的程度下,輸出反而會比 Source 的字串還要長。
//using System.IO.Compression; void Main() { string text = "OptionPostal,OptionClassType,OptionTalentItem"; text.Length.Dump(); /* 45 */ string compressBase64 = compress(text); compressBase64.Length.Dump(); /* 76 */ compressBase64.Dump(); /* H4sIAAAAAAAEAPMvKMnMzwvILy5JzNHxB3OccxKLi0MqC1Kh/JDEnNS8Es+S1FwAaY6qVC0AAAA= */ string decompressText = decompress(compressBase64); decompressText.Dump(); /* OptionPostal,OptionClassType,OptionTalentItem */ text = "OptionPostal,OptionClassType,OptionTalentItem,OptionPostal,OptionClassType,OptionTalentItem,OptionPostal,OptionClassType,OptionTalentItem,OptionPostal,OptionClassType,OptionTalentItem"; text.Length.Dump(); /* 183 */ compressBase64 = compress(text); compressBase64.Length.Dump(); /* 84 */ compressBase64.Dump(); /* H4sIAAAAAAAEAPMvKMnMzwvILy5JzNHxB3OccxKLi0MqC1Kh/JDEnNS8Es+S1FyowCBQDQBPmlWktwAAAA== */ } /*壓縮*/ private static string compress(string text) { if (string.IsNullOrEmpty(text)) { return text; } byte[] buffer = Encoding.UTF8.GetBytes(text); using (var outStream = new MemoryStream()) using (var zip = new GZipStream(outStream, CompressionMode.Compress)) { zip.Write(buffer, 0, buffer.Length); zip.Close(); string compressedBase64 = Convert.ToBase64String(outStream.ToArray()); return compressedBase64; } } /*解壓縮*/ private static string decompress(string compressed) { if (string.IsNullOrEmpty(compressed)) { return compressed; } byte[] buffer = Convert.FromBase64String(compressed); using (var inStream = new MemoryStream(buffer)) using (var outStream = new MemoryStream()) using (var zip = new GZipStream(inStream, CompressionMode.Decompress)) { zip.CopyTo(outStream); zip.Close(); string text = Encoding.UTF8.GetString(outStream.ToArray()); return text; } }
2019-07-21 15:53
產生 IP v6 的 mask byte array
int length = 121; /* total 128 */ var mask = new byte[16]; for (int i = 0; i < 16; i++) { mask[i] = 0xff; if (length > -8) { length -= 8; } if (length < 0) { mask[i] = (byte)(mask[i] << -length); } /* 當 length 出現負值時代表需要進行位移 */ } BitConverter.ToString(mask).Dump(); /* FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-80 */
2019-07-21 15:43
C# DateTimeOffset Parse Patch
DateTimeOffset 在 Parse 時會使用 Local TimeZone,這會與期望的 TimeZone 產生偏差,需要進行差值修補。
//TimeZoneInfo.GetSystemTimeZones().Dump(); /* (UTC+02:00) 開羅 */ var zone = TimeZoneInfo.FindSystemTimeZoneById("Egypt Standard Time"); zone.Dump(); var date = DateTimeOffset.Parse("2019-07-01 15:00:00"); date.Dump(); /* 2019/7/1 下午 03:00:00 +08:00 */ var diff = date.Offset - zone.BaseUtcOffset; diff.Dump(); /* 06:00:00 */ date = date.Add(diff); date.Dump(); /* 2019/7/1 下午 09:00:00 +08:00 */ date = TimeZoneInfo.ConvertTime(date, zone); date.Dump(); /* 2019/7/1 下午 03:00:00 +02:00 */
2015-03-13 13:12
[Java] Ant zip 解壓縮筆記
<unzip dest="./target_dir"> <!-- 來源的壓縮檔 --> <fileset dir="lib"> <include name="tiles-jsp-*.jar"/> </fileset> <!-- 要解出的檔案 --> <patternset> <include name="**/*.tld"/> </patternset> <!-- 解出路徑的轉換 --> <mapper type="flatten"/> </unzip>
參考文件:
Apache Ant™ User Manual : Unzip Task
Apache Ant™ User Manual : Mapper
2015-03-13 11:59
[Java] Reflection 筆記
@SuppressWarnings("unused") Object obj = new Object() { String id = "123"; public String name = "Jax"; }; Class<?> cl = obj.getClass(); for (Field field : cl.getFields()) { System.out.printf("%s = %s {%s}\n", field.getName(), field.get(obj), field.getType()); } System.out.println("======================="); for (Field field : cl.getDeclaredFields()) { System.out.printf("%s = %s {%s}\n", field.getName(), field.get(obj), field.getType()); }
Output:
name = Jax {class java.lang.String} ======================= id = 123 {class java.lang.String} name = Jax {class java.lang.String}
2015-03-06 17:12
[Java] 製作縮圖筆記
package test_image; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.File; import javax.imageio.ImageIO; public class TestImageResize { private static int targetWidth = 120; private static int targetHeight = 80; private static double targetRate = (double) targetWidth / targetHeight; public static void main(String[] args) throws Exception { System.out.printf("Target w:%s, h:%s, r:%s\n", targetWidth, targetHeight, targetRate); BufferedImage image = ImageIO.read(new File("input.jpg")); int type = image.getType(); if(type == 0) { type = BufferedImage.TYPE_INT_ARGB; } int width = image.getWidth(); int height = image.getHeight(); double rate = (double) width / height; System.out.printf("Source w:%s, h:%s, r:%s\n", width, height, rate); /* 等比例縮小至指定大小內 */ int rWidth = targetWidth; int rHeight = targetHeight; if(width < targetWidth && height < targetHeight) { rWidth = width; rHeight = height; } else if(rate > targetRate) { rHeight = (int) (targetWidth / rate); } else { rWidth = (int) (targetHeight * rate); } System.out.printf("Resize w:%s, h:%s\n", rWidth, rHeight); BufferedImage resize1 = new BufferedImage(rWidth, rHeight, type); Graphics g1 = resize1.getGraphics(); g1.drawImage(image, 0, 0, rWidth, rHeight, null); g1.dispose(); ImageIO.write(resize1, "jpg", new File("output_1.jpg")); /* 等比例縮小填滿指定大小 */ BufferedImage resize2 = new BufferedImage(targetWidth,targetHeight,type); Graphics g2 = resize2.getGraphics(); int startX = 0; int startY = 0; int size = 0; if(rate > targetRate) { startX = (int) (width - height * targetRate) / 2; size = height; } else { startY = (int) (height - width / targetRate) / 2; size = width; } System.out.printf("x:%s, y:%s, size:%s\n", startX, startY, size); g2.drawImage( image, 0, 0, targetWidth, targetHeight, startX, startY, (size + startX), (size + startY), null ); g2.dispose(); ImageIO.write(resize2, "jpg", new File("output_2.jpg")); } }
參考文件:
Graphics (Java 2 Platform SE 6)
2015-03-06 15:33
[Java] Jsoup 筆記
import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; public class TestJsoup { public static void main(String[] args) throws Exception { String url = "http://epg.dishstar.net/calendar.php?s=DISC&d=1"; // Document doc = Jsoup.parse(new URL(url), 5000); Document doc = Jsoup.connect(url) .userAgent("Mozilla/5.0") .timeout(5000).get(); Elements trs = doc.select("table tr"); for (Element tr : trs) { String time = tr.select("td:eq(0)").text(); String title = tr.select("td:eq(1)").text(); System.out.println(time + " <=> " + title); } } }
2015-03-06 11:57
Spring JavaMail 筆記
Gmail via SSL
Gmail via TLS
Sample Code
參考自:
JavaMail API – Sending email via Gmail SMTP example : Mkyong
Spring – Sending e-mail with attachment : Mkyong
Spring – Define an E-mail template in bean configuration file : Mkyong
Spring – Sending E-mail via Gmail SMTP server with MailSender : Mkyong
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="smtp.gmail.com" /> <property name="port" value="465" /> <property name="username" value="smtp-user" /> <property name="password" value="smtp-passwd" /> <property name="javaMailProperties"> <props> <prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop> <prop key="mail.smtp.auth">true</prop> </props> </property> </bean>
Gmail via TLS
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="smtp.gmail.com" /> <property name="port" value="587" /> <property name="username" value="smtp-user" /> <property name="password" value="smtp-passwd" /> <property name="javaMailProperties"> <props> <prop key="mail.smtp.starttls.enable">true</prop> <prop key="mail.smtp.auth">true</prop> </props> </property> </bean>
Sample Code
package test_mail; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; public class TestSpringMail { public static void main( String[] args ) throws Exception { AbstractApplicationContext context = new ClassPathXmlApplicationContext("test_mail/spring-mail.xml"); JavaMailSender mailSender = (JavaMailSender) context.getBean("mailSender"); sample1(mailSender); sample2(mailSender); sample3(mailSender); context.close(); } public static void sample1(JavaMailSender mailSender) throws Exception { MimeMessage mimeMessage = mailSender.createMimeMessage(); mimeMessage.setFrom("from@no-spam.com"); mimeMessage.setRecipients( Message.RecipientType.TO, "to@no-spam.com" ); mimeMessage.setSubject("Testing Subject"); mimeMessage.setContent( "<b>Testing Content.</b>", "text/html; charset=utf-8" ); mailSender.send(mimeMessage); } public static void sample2(JavaMailSender mailSender) throws Exception { MimeMessage mimeMessage = mailSender.createMimeMessage(); MimeMessageHelper message = new MimeMessageHelper(mimeMessage, "utf-8"); message.setFrom("from@no-spam.com"); message.setTo("to@no-spam.com"); message.setSubject("Testing Subject"); message.setText("<b>Testing Content.</b>", true); mailSender.send(mimeMessage); } public static void sample3(JavaMailSender mailSender) { SimpleMailMessage message = new SimpleMailMessage(); message.setFrom("from@no-spam.com"); message.setTo("to@no-spam.com"); message.setSubject("Testing Subject"); message.setText("Testing Content."); mailSender.send(message); } }
參考自:
JavaMail API – Sending email via Gmail SMTP example : Mkyong
Spring – Sending e-mail with attachment : Mkyong
Spring – Define an E-mail template in bean configuration file : Mkyong
Spring – Sending E-mail via Gmail SMTP server with MailSender : Mkyong
2015-03-04 11:33
[Java] FileFilter 筆記
File dir = new File("D:/log"); File[] list = dir.listFiles(new FileFilter(){ public boolean accept(File file) { return file.getName().endsWith(".txt"); } }); for(File file : list){ System.out.println(file.getAbsoluteFile()); } // 004.txt
2015-03-04 11:23
[Java] Object Serializable 筆記
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; class Address implements Serializable { private static final long serialVersionUID = 1L; String street; String country; public Address() {} public Address(String s, String c) { street = s; country = c; } public void setStreet(String street){ this.street = street; } public String getStreet(){ return this.street; } public void setCountry(String country){ this.country = country; } public String getCountry(){ return this.country; } @Override public String toString() { return String.format("Street : %s Country : %s", street, country); } } public class TestSerializable { public static void main(String[] args) throws Exception { Address addr = new Address("wall street", "united state"); FileOutputStream fout = new FileOutputStream("address.ser"); ObjectOutputStream oos = new ObjectOutputStream(fout); oos.writeObject(addr); oos.close(); FileInputStream fin = new FileInputStream("address.ser"); ObjectInputStream ois = new ObjectInputStream(fin); Address addr2 = (Address) ois.readObject(); ois.close(); System.out.println(addr2); // Street : wall street Country : united state } }
參考自:
How to read an Object from file in Java : Mkyong
How to write an Object to file in Java : Mkyong
Understand the serialVersionUID : Mkyong
2015-03-01 20:14
[Java] Jackson Json Parser 筆記
Object Encode / Decode
Parser to Map
Encode Date
參考自:FasterXML/jackson-databind · GitHub
import java.util.Arrays; import java.util.Date; import com.fasterxml.jackson.databind.ObjectMapper; class Album { private int id; private String title; private Date date; private String[] list; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public String[] getList() { return list; } public void setList(String[] list) { this.list = list; } @Override public String toString() { return String.format("id: %s, title: %s, date: %s, list: %s", id, title, date, Arrays.toString(list) ); } } public class TestJackson { public static void main(String[] args) throws Exception { Album album = new Album(); album.setId(1); album.setTitle("Go Go Go!");; album.setDate(new Date()); album.setList(new String[]{"Love", "Despair"}); ObjectMapper jsonMapper = new ObjectMapper(); String json = jsonMapper.writeValueAsString(album); System.out.println(json); // {"id":1,"title":"Go Go Go!","date":1425211903948,"list":["Love","Despair"]} Album album2 = jsonMapper.readValue(json, Album.class); System.out.println(album2); // id: 1, title: Go Go Go!, date: Sun Mar 01 20:11:43 CST 2015, list: [Love, Despair] } }
Parser to Map
ObjectMapper jsonMapper = new ObjectMapper(); Map<String,String> map; map = jsonMapper.readValue( "{\"name\":\"jax\", \"age\":\"31\"}", new TypeReference<HashMap<String,String>>(){} ); System.out.println(map); // {age=31, name=jax} jsonMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); jsonMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); map = jsonMapper.readValue( "{name:'jax', age:'31'}", new TypeReference<HashMap<String,String>>(){} ); System.out.println(map); // {age=31, name=jax}
Encode Date
Date date = new Date(); String json; ObjectMapper jsonMapper = new ObjectMapper(); json = jsonMapper.writeValueAsString(date); System.out.println(json); // 1425211840183 jsonMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); json = jsonMapper.writeValueAsString(date); System.out.println(json); // "2015-03-01T12:10:40.183+0000"
參考自:FasterXML/jackson-databind · GitHub
訂閱:
文章 (Atom)