How to pass a table type with an array field to a function in postgresql
This sort of thing gets complicated.  I am working on some related projects right now.  The basic tweak is that PostgreSQL uses a format which uses double quotes internally in tuple representation to represent literal values, so:

SELECT save_book('(179,the art of war,fiction,"{190,220}")'::book);


should work.  In essence a neat trick is creating a csv and enclosing in tuple or array identifiers.  The big issue is that you have to deal with escaping (doubling quotes at every level as needed).  So the following is exactly equivalent:

SELECT save_book('(179,"the art of war","fiction","{""190"",""220""}")'::book);


The second approach is to use a row constructor:

SELECT save_book(row(179,'the art of war','fiction', array[190,220])::book);


The first solution has the obvious advantage of being able to take advantage of existing programming frameworks for CSV generation and escaping.  The second is cleanest in SQL.  They can be mixed and matched.