fastjson Request passing context information to plugins

lsmd5eda  于 5个月前  发布在  其他
关注(0)|答案(9)|浏览(56)

For the following code:

public class Record {

    @JSONField(format = "yyyy-MMM-dd")
    public Date date1 = new Date();

    @JSONField(format = "yyyyMMdd")
    public Date date2 = date1;

    @JSONField(format = "yyyy_MM_dd hh:mm")
    public DateTime dateTime = DateTime.now();
}
``

and I use FastJSON to serialize the `Record` instance as:

```java
System.out.println(JSON.toJSONString(new Record()));

I will get something like:

{
	"date1":"2018-Jan-06",
	"date2":"20180106",
	"dateTime":{
		"afterNow":false,
		"beforeNow":true,
		"centuryOfEra":20,
		"chronology":{
			"zone":{
				"fixed":false,
				"iD":"Australia/Sydney",
                ...
			}
		},
        ...
		"zone":{"$ref":"$.null.chronology.zone"}
	}
}

Obviously fastjson doesn't support serialization of joda DateTime type. thus I want to create my own ObjecSerializer to implement that, here is something I can write:

public class JodaDateTimeSerializer implements ObjectSerializer {
    @Override
    public void write(
        JSONSerializer serializer, 
        Object object, 
        Object fieldName, 
        Type fieldType, 
        int features
    ) throws IOException {
        SerializeWriter out = serializer.getWriter();
        if (object == null) {
            out.writeNull();
        } else {
            Class cls = object.getClass();
            if (cls == DateTime.class) {
                // question? where can I get the JSONView annotation and the format string?
                out.writeString(object.toString());
            } else {
                out.writeString(object.toString());
            }
        }
    }
}

As it shown above my problem here is I lost the context of the serialization, the interface doesn't pass me the field context, say the @JSONView annotation and the format.

The request is to extend the ObjectSerializer and ObjectDeserializer interface so we can get the field class in order to get the context information, specifically all annotations put on that field.

44u64gxh

44u64gxh1#

Note, when I won't be able to get fieldType and fieldName information:

As the caller method passed null for those fields:

If I go further upper level caller the writeWithFormat I can see there is the format string, but it's not get passed into the next call:

fd3cxomn

fd3cxomn2#

DateTime is not a builtin class in JDK,
If you created it, so you could registry a Serializer for it.

unftdfkk

unftdfkk3#

@kimmking that's all what I mean, I have created the serializer, however I need to access the field context in the serializer, e.g. I need to know if there is a @JSONView annotation with format parameter set to something like "yyyy_MM_dd hh:mm" , so that I can serialize the DateTime data property:

cnjp1d6j

cnjp1d6j4#

fastjson dont know the type DateTime is a date type.

6ovsh4lw

6ovsh4lw5#

SerializeConfig.getGlobalInstance().put(DateTime .class, new DateCodec ());

7vhp5slm

7vhp5slm6#

@kimmking I said I have the codec for DateTime if you read my issue report carefully:

I know exactly what SerializeConfig.getGlobalInstance() does, and I use it in my app already: https://github.com/actframework/actframework/blob/master/src/main/java/act/util/JsonUtilConfig.java

My question is how can I access the field context @JSONField(format="yyyy-MM-dd hh:mm") from within the codec.

vaj7vani

vaj7vani7#

I consider this as a bug.
The build-in support for JDK8 java.time package is also not effected by format field.

see getPropertyValue() in fastjson/src/main/java/com/alibaba/fastjson/serializer/FieldSerializer.java

xtfmy6hx

xtfmy6hx8#

@wenshao what do you think about this one?

Now I have a concrete use case from our real project.

// the tooth care kit 
public class Kit {
    public int id;
    public String description;
    ...
}
// the order info encapsulate kit and quantity
public class OrderInfo {
    @DbBind @NotNull
    public Kit kit;
    public int qty;
}
// The request handler
@PostAction("orders")
public void placeKitOrders(List<OrderInfo> orders) {
    ....
}

// the JSON body for order request

{
    "orders": [
        {"kit": 1, "qty": 3}, {"kit": 2, "qty": 5}
    ]
}

Here one important thing is I need to use the kit id (in the above sample data, 1 and 2 ) to look up Kit table and fetch the corresponding record to construct a Kit instance and inject into the OrderInfo instance. Thus I need FastJSON to provide the mechanism for me to inject logic sense the annotation DbBind and get the job done.

Any idea if this could be doable(planned) in FastJSON ?

h4cxqtbf

h4cxqtbf9#

This issue is been solved as(using kimmking‘s solution’) :

FastJsonJodaDateCodec jodaDateCodec = new FastJsonJodaDateCodec(app);
        app.registerSingleton(FastJsonJodaDateCodec.class, jodaDateCodec);

        FastJsonValueObjectSerializer valueObjectSerializer = new FastJsonValueObjectSerializer();
        app.registerSingleton(FastJsonValueObjectSerializer.class, valueObjectSerializer);
        FastJsonKeywordCodec keywordCodec = new FastJsonKeywordCodec();
        FastJsonSObjectCodec sObjectCodec = new FastJsonSObjectCodec();

        config.put(DateTime.class, jodaDateCodec);

相关问题