Jackson模拟对PHP序列化反序列化
模拟结果
---------------{null}-------------
serializer --> think_serialize:N;
deserialize --> null
---------------{String}-------------
serializer --> think_serialize:s:27:"foobar好汉좋아요よし";
deserialize --> foobar好汉좋아요よし
---------------{boolean}-------------
serializer --> think_serialize:b:1;
deserialize --> true
---------------{int}-------------
serializer --> think_serialize:i:10;
deserialize --> 10
---------------{long}-------------
serializer --> think_serialize:i:1722590532191;
deserialize --> 1722590532191
---------------{double}-------------
serializer --> think_serialize:d:10.0;
deserialize --> 10.0
---------------{String[]}-------------
serializer --> think_serialize:a:2:{i:0;s:27:"foobar好汉좋아요よし";i:1;s:1:"b";}
foobar好汉좋아요よし
b
---------------{List}-------------
serializer --> think_serialize:a:3:{i:0;s:27:"foobar好汉좋아요よし";i:1;s:1:"b";i:2;s:1:"c";}
foobar好汉좋아요よし
b
c
---------------{MyClass}-------------
serializer --> think_serialize:a:4:{s:3:"foo";s:4:"foo1";s:3:"bar";i:1;s:4:"tags";a:2:{i:0;s:2:"c1";i:1;s:2:"d1";}s:7:"myClass";a:4:{s:3:"foo";s:4:"foo2";s:3:"bar";i:2;s:4:"tags";a:2:{i:0;s:2:"c2";i:1;s:2:"d2";}s:7:"myClass";a:4:{s:3:"foo";s:27:"foobar好汉좋아요よし";s:3:"bar";i:3;s:4:"tags";a:2:{i:0;s:27:"foobar好汉좋아요よし";i:1;s:2:"d3";}s:7:"myClass";N;}}}
{"foo":"foo1","bar":1,"tags":["c1","d1"],"myClass":{"foo":"foo2","bar":2,"tags":["c2","d2"],"myClass":{"foo":"foobar好汉좋아요よし","bar":3,"tags":["foobar好汉좋아요よし","d3"],"myClass":null}}}
---------------{ObjectNode}-------------
serializer --> think_serialize:a:3:{s:8:"foodInfo";a:4:{s:3:"bar";i:2;s:3:"foo";s:4:"foo2";s:7:"object1";a:2:{s:27:"foobar好汉좋아요よし";i:2;s:8:"foodInfo";s:27:"foobar好汉좋아요よし";}s:5:"array";a:3:{i:0;s:2:"aa";i:1;s:3:"bbb";i:2;s:2:"cc";}}s:9:"tableInfo";a:3:{i:0;s:2:"aa";i:1;s:3:"bbb";i:2;s:2:"cc";}s:4:"name";s:8:"zhangsan";}
{"foodInfo":{"bar":2,"foo":"foo2","object1":{"foobar好汉좋아요よし":2,"foodInfo":"foobar好汉좋아요よし"},"array":["aa","bbb","cc"]},"tableInfo":["aa","bbb","cc"],"name":"zhangsan"}
PhpGenerator
package org.anycu.common.core.jackson.dataformat;
import com.fasterxml.jackson.core.Base64Variant;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.core.SerializableString;
import com.fasterxml.jackson.core.base.GeneratorBase;
import com.fasterxml.jackson.core.json.JsonWriteContext;
import java.io.IOException;
import java.io.Writer;
import java.math.BigDecimal;
import java.math.BigInteger;
public class PhpGenerator extends GeneratorBase {
private static final String DELIM = ":";
private static final String EOR = ";";
private final Writer writer;
private PhpWriteContext context;
public PhpGenerator(int features, ObjectCodec codec, Writer out) {
super(features, codec);
this.writer = out;
this.context = PhpWriteContext.createRootContext(out);
}
@Override
public Object getOutputTarget() {
return this.writer;
}
@Override
public void writeStartArray() throws IOException {
writeArrayIndexIfArray();
this.context = this.context.createChildArrayContext();
}
@Override
public void writeEndArray() throws IOException {
if (!context.inArray()) {
_reportError("Current context not an ARRAY but " + context.getTypeDesc());
}
this.flushArray();
}
@Override
public void writeStartObject() throws IOException {
writeArrayIndexIfArray();
context = context.createChildObjectContext();
}
@Override
public void writeEndObject() throws IOException {
if (!context.inObject()) {
_reportError("Current context not an object but " + context.getTypeDesc());
}
this.flushArray();
}
@Override
public void writeFieldName(String name) throws IOException {
int status = context.writeFieldName(name);
if (status == JsonWriteContext.STATUS_EXPECT_VALUE) {
_reportError("Can not write a field name, expecting a value");
}
writeString(name);
}
@Override
public void writeFieldName(SerializableString name) throws IOException {
writeFieldName(name.getValue());
}
@Override
public void writeString(String text) throws IOException {
writeArrayIndexIfArray();
Integer count = byteCount(text);
this.context.append("s");
this.context.append(DELIM);
this.context.append(count.toString());
this.context.append(DELIM);
this.context.append("\"");
this.context.append(text);
this.context.append("\"");
this.context.append(EOR);
this.context.writeValue();
}
@Override
public void writeString(char[] text, int offset, int len) throws IOException {
writeString(new String(text).substring(offset, len));
}
@Override
public void flush() throws IOException {
writer.flush();
}
@Override
protected void _releaseBuffers() {
throw new UnsupportedOperationException("Not supported release buffers.");
}
@Override
protected void _verifyValueWrite(String typeMsg) throws IOException {
}
@Override
public void writeRawUTF8String(byte[] text, int offset, int length) throws IOException {
throw new UnsupportedOperationException("Not supported write raw UTF8 String.");
}
@Override
public void writeUTF8String(byte[] text, int offset, int length) throws IOException {
throw new UnsupportedOperationException("Not supported write UTF8 String.");
}
@Override
public void writeRaw(String text) throws IOException {
throw new UnsupportedOperationException("Not supported write raw.");
}
@Override
public void writeRaw(String text, int offset, int len) throws IOException {
throw new UnsupportedOperationException("Not supported write raw String.");
}
@Override
public void writeRaw(char[] text, int offset, int len) throws IOException {
throw new UnsupportedOperationException("Not supported write raw char[].");
}
@Override
public void writeRaw(char c) throws IOException {
throw new UnsupportedOperationException("Not supported write raw char.");
}
@Override
public void writeBinary(Base64Variant b64variant, byte[] data, int offset, int len) throws IOException {
throw new UnsupportedOperationException("Not supported write binary.");
}
@Override
public void writeNumber(int v) throws IOException {
this.writeInt(v);
}
@Override
public void writeNumber(long v) throws IOException {
this.writeInt(v);
}
@Override
public void writeNumber(BigInteger v) throws IOException {
this.writeInt(v);
}
@Override
public void writeNumber(double d) throws IOException {
writeDouble(d);
}
@Override
public void writeNumber(float f) throws IOException {
writeDouble(f);
}
@Override
public void writeNumber(BigDecimal dec) throws IOException {
writeDouble(dec);
}
@Override
public void writeNumber(String encodedValue) throws IOException, UnsupportedOperationException {
throw new UnsupportedOperationException("Not supported write number String.");
}
@Override
public void writeBoolean(boolean state) throws IOException {
writeArrayIndexIfArray();
context.append("b");
context.append(DELIM);
context.append(state ? "1" : "0");
context.append(EOR);
context.writeValue();
}
@Override
public void writeNull() throws IOException {
writeArrayIndexIfArray();
this.context.append("N");
this.context.append(EOR);
this.context.writeValue();
}
private void writeArrayIndexIfArray() throws IOException {
if (this.context.inArray()) {
this.context.append("i");
this.context.append(DELIM);
this.context.append(Integer.toString(this.context.getFieldCount()));
this.context.append(EOR);
this.context.incrementFieldCount();
}
}
private void writeInt(Number v) throws IOException {
writeArrayIndexIfArray();
this.context.append("i");
this.context.append(DELIM);
this.context.append(v.toString());
this.context.append(EOR);
this.context.writeValue();
}
private void writeDouble(Number v) throws IOException {
writeArrayIndexIfArray();
this.context.append("d");
this.context.append(DELIM);
this.context.append(v.toString());
this.context.append(EOR);
this.context.writeValue();
}
private void flushArray() throws IOException {
this.context.getWriter().close();
Writer prefixWriter = context.getParent().getWriter();
prefixWriter.append("a");
prefixWriter.append(DELIM);
prefixWriter.append(Integer.toString(context.getFieldCount()));
prefixWriter.append(DELIM);
prefixWriter.append("{");
prefixWriter.append(context.getWriter().toString());
prefixWriter.append("}");
this.context = this.context.getParent();
}
public int byteCount(String text) {
int count = 0;
char[] chars = text.toCharArray();
for (char ch : chars) {
if ((ch >= 0x0001) && (ch <= 0x007F)) {
count++;
} else if (ch > 0x07FF) {
count += 3;
} else {
count += 2;
}
}
return count;
}
}
PhpParser
package org.anycu.common.core.jackson.dataformat;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.base.ParserMinimalBase;
import com.fasterxml.jackson.core.io.IOContext;
import com.fasterxml.jackson.core.io.NumberInput;
import com.fasterxml.jackson.core.json.JsonReadContext;
import com.fasterxml.jackson.core.json.PackageVersion;
import java.io.IOException;
import java.io.PushbackReader;
import java.io.Reader;
import java.math.BigDecimal;
import java.math.BigInteger;
public class PhpParser extends ParserMinimalBase {
private static final char[] EXPECTED_CHARS = new char[]{'i', ':', '0', ';'};
private static final int INT_SEMICOLON = ';';
private final IOContext ioContext;
private final PushbackReader reader;
private boolean closed;
private ObjectCodec objectCodec;
private JsonReadContext parsingContext;
private String currentValue;
private int numTypesValid = NR_UNKNOWN;
private int numberInt;
private long numberLong;
private BigInteger numberBigInt;
public PhpParser(IOContext iOContext, Reader reader, int features, ObjectCodec objectCodec) {
super(features);
this.objectCodec = objectCodec;
this.reader = new PushbackReader(reader, EXPECTED_CHARS.length);
this.ioContext = iOContext;
this.parsingContext = JsonReadContext.createRootContext(null);
}
@Override
public JsonToken nextToken() throws IOException {
if (this.closed) {
return null;
}
int i = this.reader.read();
if (i == INT_RCURLY) {
_currToken = this.parsingContext.inObject() ?
JsonToken.END_OBJECT : JsonToken.END_ARRAY;
this.parsingContext = this.parsingContext.getParent();
return _currToken;
}
if (this.parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) {
determineNextToken(i);
this.parsingContext.setCurrentName(currentValue);
_currToken = JsonToken.FIELD_NAME;
return _currToken;
}
if (this.parsingContext.inArray() && !isExpectedStartArrayToken()) {
consume(INT_COLON);
consumeValuesAndExpected(INT_SEMICOLON);
i = this.reader.read();
}
_currToken = determineNextToken(i);
return _currToken;
}
private JsonToken determineNextToken(int i) throws IOException {
JsonToken t = null;
switch ((char) i) {
case 'i':
t = parseInt();
break;
case 'd':
t = parseFloat();
break;
case 'b':
t = parseBoolean();
break;
case 's':
t = parseString();
consume(INT_SEMICOLON);
break;
case 'a':
consume(INT_COLON);
consumeValuesAndExpected(INT_COLON);
consume(INT_LCURLY);
/**
* 在php中数组对应java中对象和数组;
* 此处没有想到更好的方式;试着预读后面字段的类型i和s区分吧;如果期望出现时 "i:0;" 就认定是数组;
*/
if (isExpectedStartArray()) {
this.parsingContext = this.parsingContext.createChildArrayContext(0, 0);
t = JsonToken.START_ARRAY;
} else {
this.parsingContext = this.parsingContext.createChildObjectContext(0, 0);
t = JsonToken.START_OBJECT;
}
break;
case 'N':
t = JsonToken.VALUE_NULL;
consume(INT_SEMICOLON);
break;
default:
_reportError("Unknown type: '" + ((char) i) + "'");
}
return t;
}
@Override
public NumberType getNumberType() throws IOException {
if (_currToken == JsonToken.VALUE_NUMBER_INT) {
final String text = currentValue.trim();
final boolean numberNegative = isNumberNegative(text);
final int len = isIntNumber(text);
if (len > 0) {
if (len <= 9) {
numberInt = NumberInput.parseInt(text);
numTypesValid = NR_INT;
return NumberType.INT;
} else if (len <= 18) {
long l = NumberInput.parseLong(text);
if (len == 10) {
if (numberNegative) {
if (l >= MIN_INT_L) {
numberInt = (int) l;
numTypesValid = NR_INT;
return NumberType.INT;
}
} else {
if (l <= MAX_INT_L) {
numberInt = (int) l;
numTypesValid = NR_INT;
return NumberType.INT;
}
}
}
numberLong = l;
numTypesValid = NR_LONG;
return NumberType.LONG;
} else if (len == 19) {
final boolean stillLong = NumberInput.inLongRange(numberNegative ?
text.substring(1) : text, numberNegative);
if (stillLong) {
numberLong = NumberInput.parseLong(text);
numTypesValid = NR_LONG;
return NumberType.LONG;
}
} else {
streamReadConstraints().validateIntegerLength(text.length());
numberBigInt = NumberInput.parseBigInteger(
text, isEnabled(StreamReadFeature.USE_FAST_BIG_NUMBER_PARSER));
numTypesValid = NR_BIGINT;
return NumberType.BIG_INTEGER;
}
}
} else if (_currToken == JsonToken.VALUE_NUMBER_FLOAT) {
return NumberType.DOUBLE;
} else {
_reportError("Current token (%s) not numeric, can not use numeric value accessors", this._currToken);
}
return null;
}
private boolean isNumberNegative(String text) {
final int len = text.length();
if (len > 0) {
return text.charAt(0) == '-';
}
return false;
}
protected final int isIntNumber(String text) {
final int len = text.length();
if (len > 0) {
char c = text.charAt(0);
final int start = (c == '-') ? 1 : 0;
for (int i = start; i < len; ++i) {
int ch = text.charAt(i);
if (ch > '9' || ch < '0') {
return -1;
}
}
return len - start;
}
return 0;
}
@Override
protected void _handleEOF() throws JsonParseException {
throw new UnsupportedOperationException("Not supported method#_handleEOF.");
}
@Override
public String getCurrentName() throws IOException {
if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) {
JsonReadContext parent = this.parsingContext.getParent();
return parent.getCurrentName();
}
return this.parsingContext.getCurrentName();
}
@Override
public ObjectCodec getCodec() {
return this.objectCodec;
}
@Override
public void setCodec(ObjectCodec oc) {
this.objectCodec = oc;
}
@Override
public Version version() {
return PackageVersion.VERSION;
}
@Override
public void close() throws IOException {
if (!this.closed) {
this.closed = true;
this.reader.close();
}
}
@Override
public boolean isClosed() {
return this.closed;
}
@Override
public JsonStreamContext getParsingContext() {
return this.parsingContext;
}
@Override
public JsonLocation getCurrentLocation() {
return new JsonLocation(ioContext == null ? null : ioContext.contentReference(), 0, 0, 0);
}
@Override
public JsonLocation getTokenLocation() {
return JsonLocation.NA;
}
@Override
public void overrideCurrentName(String name) {
throw new UnsupportedOperationException("Not supported method#overrideCurrentName.");
}
@Override
public String getText() throws IOException {
return this.currentValue;
}
@Override
public char[] getTextCharacters() throws IOException {
return this.currentValue.toCharArray();
}
@Override
public boolean hasTextCharacters() {
return this.currentValue != null && this.currentValue.length() > 0;
}
@Override
public Number getNumberValue() throws IOException {
if ((numTypesValid & NR_INT) != 0) {
return numberInt;
}
if ((numTypesValid & NR_LONG) != 0) {
return numberLong;
}
if ((numTypesValid & NR_BIGINT) != 0) {
return numberBigInt;
}
return null;
}
@Override
public int getIntValue() throws IOException {
return numberInt;
}
@Override
public long getLongValue() throws IOException {
return numberLong;
}
@Override
public BigInteger getBigIntegerValue() throws IOException {
return numberBigInt;
}
@Override
public float getFloatValue() throws IOException {
return Float.parseFloat(this.currentValue);
}
@Override
public double getDoubleValue() throws IOException {
return Double.parseDouble(this.currentValue);
}
@Override
public BigDecimal getDecimalValue() throws IOException {
return new BigDecimal(this.currentValue);
}
@Override
public int getTextLength() throws IOException {
return this.currentValue.length();
}
@Override
public String getValueAsString() throws IOException {
return this.currentValue;
}
@Override
public int getTextOffset() throws IOException {
throw new UnsupportedOperationException("Not supported method#getTextOffset.");
}
@Override
public byte[] getBinaryValue(Base64Variant b64variant) throws IOException {
throw new UnsupportedOperationException("Not supported method#getBinaryValue.");
}
private JsonToken parseString() throws IOException {
int strLen = readValueLength();
int ch = this.reader.read();
if (ch != '"') {
reportUnexpectedChar(ch, '"');
}
StringBuilder b = new StringBuilder(strLen);
int byteCount = 0;
while (byteCount != strLen) {
ch = this.reader.read();
b.append((char) ch);
if ((ch >= 0x0001) && (ch <= 0x007F)) {
byteCount++;
} else if (ch > 0x07FF) {
byteCount += 3;
} else {
byteCount += 2;
}
}
this.currentValue = b.toString();
ch = this.reader.read();
if (ch != '"') {
reportUnexpectedChar(ch, '"');
}
return JsonToken.VALUE_STRING;
}
private String readNextValue() throws IOException {
int c = this.reader.read();
if (c != INT_COLON) {
reportUnexpectedChar(c, INT_COLON);
}
StringBuilder b = new StringBuilder();
c = this.reader.read();
while (c != -1 && c != INT_SEMICOLON) {
b.append((char) c);
c = this.reader.read();
}
return b.toString();
}
private JsonToken parseBoolean() throws IOException {
String nextValue = readNextValue();
if ("1".equals(nextValue)) {
this.currentValue = "true";
return JsonToken.VALUE_TRUE;
} else if ("0".equals(nextValue)) {
this.currentValue = "false";
return JsonToken.VALUE_FALSE;
} else {
this.currentValue = nextValue;
return Boolean.parseBoolean(nextValue) ? JsonToken.VALUE_TRUE : JsonToken.VALUE_FALSE;
}
}
private JsonToken parseFloat() throws IOException {
this.currentValue = readNextValue();
return JsonToken.VALUE_NUMBER_FLOAT;
}
private JsonToken parseInt() throws IOException {
this.currentValue = readNextValue();
return JsonToken.VALUE_NUMBER_INT;
}
/**
* 读取下一个字段的长度
*/
private int readValueLength() throws IOException {
int c = this.reader.read();
if (c != INT_COLON) {
return 0;
}
StringBuilder b = new StringBuilder();
c = this.reader.read();
while (c != -1 && c != INT_COLON) {
b.append((char) c);
c = this.reader.read();
}
if (b.length() > 0) {
return Integer.parseInt(b.toString());
}
return 0;
}
/**
* 预读后面4位,判断是否数组开头,否则推回已读取的字符
*/
private boolean isExpectedStartArray() throws IOException {
int length = EXPECTED_CHARS.length;
char[] buffer = new char[length];
int numRead = 0;
// 逐字符读取并检查
for (int i = 0; i < length; i++) {
int ch = this.reader.read();
if (ch == -1) {
// 如果到达流末尾,推回已读取的字符
if (numRead > 0) {
this.reader.unread(buffer, 0, numRead);
}
return false;
}
buffer[i] = (char) ch;
numRead++;
if (buffer[i] != EXPECTED_CHARS[i]) {
// 如果字符不匹配,推回已读取的字符
this.reader.unread(buffer, 0, numRead);
return false;
}
}
return true;
}
/**
* 消费连续数字并期望接下来是val字符
* 例如:3: 0;
*/
private void consumeValuesAndExpected(int val) throws IOException {
int ch = this.reader.read();
while (ch != -1 && ch <= '9' && ch >= '0') {
ch = this.reader.read();
}
if (ch != -1 && ch != val) {
reportUnexpectedChar(ch, val);
}
}
private void consume(int val) throws IOException {
int ch = this.reader.read();
if (ch != -1 && ch != val) {
reportUnexpectedChar(ch, val);
}
}
private void reportUnexpectedChar(int got, int expected) throws JsonParseException {
_reportError("Expected " + ((char) expected) + " but got '" + ((char) got) + "'");
}
}
PhpWriteContext
package org.anycu.common.core.jackson.dataformat;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.json.JsonWriteContext;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
public class PhpWriteContext {
private final JsonWriteContext jsonContext;
private final PhpWriteContext parent;
private PhpWriteContext child;
private Writer writer;
private int fieldCount = 0;
protected PhpWriteContext(JsonWriteContext jsonContext, PhpWriteContext parent, Writer writer) {
this.jsonContext = jsonContext;
this.parent = parent;
this.writer = writer;
if (this.writer == null) {
this.writer = new StringWriter();
}
}
public static PhpWriteContext createRootContext(Writer writer) {
return new PhpWriteContext(JsonWriteContext.createRootContext(null), null, writer);
}
public final PhpWriteContext createChildArrayContext() {
this.child = new PhpWriteContext(jsonContext.createChildArrayContext(), this, null);
return this.child;
}
public final PhpWriteContext createChildObjectContext() {
this.child = new PhpWriteContext(jsonContext.createChildObjectContext(), this, null);
return this.child;
}
public final PhpWriteContext getParent() {
return this.parent;
}
public final int writeFieldName(String name) throws JsonProcessingException {
this.fieldCount++;
return this.jsonContext.writeFieldName(name);
}
public final int writeValue() {
return this.jsonContext.writeValue();
}
public int getFieldCount() {
return this.fieldCount;
}
public void incrementFieldCount() {
this.fieldCount++;
}
public Writer getWriter() {
return this.writer;
}
public void append(CharSequence string) throws IOException {
this.writer.append(string);
}
public boolean inObject() {
return this.jsonContext.inObject();
}
public boolean inArray() {
return this.jsonContext.inArray();
}
public String getTypeDesc() {
return this.jsonContext.typeDesc();
}
}
PhpJsonFactory
package org.anycu.common.core.jackson.dataformat;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.format.InputAccessor;
import com.fasterxml.jackson.core.format.MatchStrength;
import com.fasterxml.jackson.core.io.IOContext;
import java.io.*;
import java.net.URL;
public class PhpJsonFactory extends JsonFactory {
public final static String FORMAT_NAME_PHP = "PHP";
@Override
public String getFormatName() {
return FORMAT_NAME_PHP;
}
@Override
public MatchStrength hasFormat(InputAccessor acc) throws IOException {
return MatchStrength.FULL_MATCH;
}
/**
* **************************************
* Overridden Generator factory methods
* **************************************
*/
@Override
public PhpGenerator createGenerator(OutputStream out) throws IOException {
return this.createGenerator(out, JsonEncoding.UTF8);
}
@Override
public PhpGenerator createGenerator(OutputStream out, JsonEncoding encode) throws IOException {
IOContext context = _createContext(_createContentReference(out), false);
context.setEncoding(encode);
return _createGenerator(this._createWriter(out, encode), context);
}
@Override
protected PhpGenerator _createGenerator(Writer out, IOContext context) throws IOException {
return new PhpGenerator(0, _objectCodec, out);
}
protected Writer _createWriter(OutputStream out, JsonEncoding encode) throws IOException {
return new OutputStreamWriter(out, encode.getJavaName());
}
/**
* **************************************
* Overridden Parser factory methods
* **************************************
*/
@Override
public PhpParser createParser(byte[] data) throws IOException {
IOContext context = _createContext(_createContentReference(data), Boolean.TRUE);
return this._createParser(data, 0, data.length, context);
}
@Override
public PhpParser createParser(byte[] data, int offset, int len) throws IOException {
IOContext context = _createContext(_createContentReference(data, offset, len), Boolean.TRUE);
return this._createParser(data, offset, len, context);
}
@Override
public PhpParser createParser(File f) throws IOException {
IOContext context = _createContext(_createContentReference(f), Boolean.TRUE);
InputStream inputStream = new FileInputStream(f);
return this._createParser(inputStream, context);
}
@Override
public PhpParser createParser(InputStream in) throws IOException {
IOContext context = _createContext(_createContentReference(in), Boolean.FALSE);
return this._createParser(in, context);
}
@Override
public PhpParser createParser(Reader r) {
IOContext context = _createContext(_createContentReference(r), Boolean.TRUE);
return this._createParser(r, context);
}
@Override
public PhpParser createParser(String content) {
return this.createParser(new StringReader(content));
}
@Override
public PhpParser createParser(URL url) throws IOException {
IOContext context = _createContext(_createContentReference(url), Boolean.TRUE);
InputStream inputStream = _optimizedStreamFromURL(url);
return this._createParser(inputStream, context);
}
@Override
protected PhpParser _createParser(byte[] data, int offset, int len, IOContext context) throws IOException {
JsonEncoding enc = context.getEncoding();
Reader reader = this._createReader(data, offset, len, enc);
return new PhpParser(context, reader, _parserFeatures, _objectCodec);
}
@Override
protected PhpParser _createParser(InputStream in, IOContext context) throws IOException {
JsonEncoding enc = context.getEncoding();
Reader reader = this._createReader(in, enc);
return new PhpParser(context, reader, _parserFeatures, _objectCodec);
}
@Override
protected PhpParser _createParser(Reader reader, IOContext context) {
return new PhpParser(context, reader, _parserFeatures, _objectCodec);
}
protected Reader _createReader(byte[] data, int offset, int len, JsonEncoding jsonEncoding) throws IOException {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data, offset, len);
return new InputStreamReader(byteArrayInputStream, jsonEncoding.getJavaName());
}
protected Reader _createReader(InputStream inputStream, JsonEncoding encoding) throws IOException {
return new InputStreamReader(inputStream, encoding.getJavaName());
}
}
PhpJacksonUtils
package org.anycu.common.core.utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.experimental.UtilityClass;
import org.anycu.common.core.jackson.dataformat.PhpJsonFactory;
import org.apache.commons.lang3.StringUtils;
import java.io.UncheckedIOException;
@UtilityClass
public class PhpJacksonUtils {
private static final String PREFIX = "think_serialize:";
private static final ObjectMapper PHP_MAPPER = new ObjectMapper(new PhpJsonFactory());
public static String serializer(Object value) {
try {
return PREFIX + PHP_MAPPER.writeValueAsString(value);
} catch (JsonProcessingException e) {
throw new UncheckedIOException(e);
}
}
public static JsonNode deserialize(String value) {
if (StringUtils.isEmpty(value)) {
return NullNode.getInstance();
}
if (StringUtils.startsWith(value, PREFIX)) {
value = value.substring(PREFIX.length());
}
try {
return PHP_MAPPER.readTree(value);
} catch (JsonProcessingException e) {
e.printStackTrace();
throw new UncheckedIOException(e);
}
}
}