Lazy Diary @ Hatena Blog

PowerShell / Java / miscellaneous things about software development, Tips & Gochas. CC BY-SA 4.0/Apache License 2.0

Get a deep copy of an object with non-serializable fields with Jackson

Background

When you want to get a deep copy of an object, you can use ObjectOutputStream/ObjectInputStream and serialize/deserialize the target object *1 ((Note that SerializationUtils.clone() in Spring Framework requires the class of the target object implements Serializable. ObjectOutputStream#writeObject() doesn't have such restriction)).

Problem

In this method, you will get NotSerializableException if the object contains non-serializable fields like MultipartFile of Spring Framework.

To avoid this exception, you have to add the transient modifier to the non-serializable fields. So you have to have control of the class of the object to adopt this workaround. For the class that you don't have control of or that is in libraries, you can't take this approach.

Solution

You can use Jackson's ObjectMapper#writeValueAsString() and ObjectMapper#readValue() to clone an object. This method throws InvalidDefinitionException if the object has non-serializable fields. You can use @JsonIgnoreType and ObjectMapper#addMixIn() to ignore non-serializable fields according to their type without changing the definition of the class.

For example, you can ignore the MultipartFile fields (for single file upload) and MultipartFile[] fields (for multiple file upload) like this:

private Object makeClone(Object obj) {
    ObjectMapper mapper = new ObjectMapper();
    mapper.addMixIn(MultipartFile.class, JacksonMixInForIgnoreType.class);
    mapper.addMixIn(MultipartFile[].class, JacksonMixInForIgnoreType.class);
    try {
        return mapper.readValue(mapper.writeValueAsString(obj), obj.getClass());
    } catch (JsonProcessingException e) {
        throw new RuntimeException(e);
    }
}

@JsonIgnoreType
class JacksonMixInForIgnoreType {}

Restriction

  • You can't ignore the field like List<MultipartFile> fileArray; with this strategy. It seems there is no way to ignore the collection of a specific class.
  • If the target object has two or more references to a single instance, they will be different objects on the clone.

姓名の分割が行える形態素解析器

前提

姓・名にJIS第1・第2水準外の文字が含まれている日本人はどれくらいの割合でいるか?を調べるときのサンプルとして、国会議員名簿が都合がいい(PCで表示できない文字はその旨書いておいてくれているから)。

問題

姓名が区切りなしで書かれている場合、機械的に処理しようとしたときにどこまでが姓でどこまでが名かわからない。

疑問

参議院サイトの議員名簿と衆議院サイトの議員名簿の違い

スクレイピングするときにつらい……

# 違い 参議院 衆議院
1 ページのまとめかた 全議員名が1ページにまとまっている 50音順にページが分かれている
2 通称名の記載 通称名を使っている場合、通称名と本名がそれぞれ書いてある 通称名か本名かの区別なく書いてある
3 姓名の分かち書き 姓と名のあいだにかならずスペースがある 姓と名のあいだにスペースがある人とない人がいる
4 「君」づけの有無 氏名の最後に「君」をつけていない 氏名の最後に「君」をつけている
5 正字の示しかた 記載字と正字が違う場合「<正字>」のようなリンクがある 別ページのみに記載され、リンクなし
6 会派に属さない議員の書き方 「無所属」と書かれる 「無」と書かれる
7 小選挙区の書き方 ブロックがないので「神奈川」のように書かれる ブロックごとに「第◯区」があるので「神奈川1」のように書かれる
8 比例当選の書き方 ブロックがないので「比例」だけ 「(比)北関東」のようにブロック名がある

DevRelとかCCoEとかOSPOの存続

企業内においてDevRel*1とかCCoE*2とかOSPO*3とかの部門を設けているケースはけっこうある。では、それらの部門はコスト部門となっている場合と、プロフィット部門となっている場合のどちらが多いのか?またプロフィット部門の場合、コスト部門の場合のそれぞれにおいて、その原資はどこからどのように得られているのか?どのような理由で設置され、それを受けてどのような指標で経営層から評価されているのか?また設置後に廃止された場合、どのような理由で廃止されたのか?

CCoEを設けようとか、OSPOを設けようという話はちょいちょい目にする。だけど、

  • 設置した部門をどう存続させるか?
  • 経営上の判断をする管掌者が、部門を設置した理由や経緯や必要性を把握しているうちはいいのだが、異動で管掌者が変わったときにどうするか?
  • 企業全体の業績が悪化した状況下で、どのように価値を提供し続けるか?

みたいな話を目にしないんだよなぁ。

まぁそりゃそうか、一度OSPOを設置したあとに「OSPOを廃止しました」と対外的に言ってしまったら、今度の経営層はオープンソースソフトウェアのエコシステムに興味がないんだと思われる可能性が大だからな……

PostgreSQLがORDBMSってどういうこと?

GAITの試験問題サンプル*1を見ていて気付いたんだけど、PostgreSQLのオフィシャルサイトではPostgreSQLはobject-relational database systemだと謳っている*2。これってどういうことなの?Wikipediaにあるとおり*3普通のrelational databaseなのでは?と思っていたんだけど、どうも型定義や継承ができるから単なるrelational databaseでなくobject-relational databaseだ*4*5ということらしい。

実はCREATE TABLEPostgreSQLのマニュアル上では「新規テーブルの作成」でなく「新規クラスの作成」として説明されている*6。一方でMySQLのマニュアル*7SQL Serverのマニュアル*8ではちゃんと「テーブルを作成」と書かれている。