java可以将任意对象序列化为一段内存流,也可以反序列化回对象。
此代码用于dump序列化内容流,是用了Jsoncpp作为父类。
主要参考了https://github.com/NickstaDB/SerializationDumper这个项目。
#pragma once
#include <string>
#include <vector>
#include <cassert>
#include "FStream.h"
#include "json/json.h"
// #ifdef _DEBUG
// #pragma comment(lib, "jsoncpp/lib_json_mtd.lib")
// #else
// #pragma comment(lib, "jsoncpp/lib_json_mt.lib")
// #endif // _DEBUG
/*
Java序列化内容(以0xACED开头)解析工具,转为jsoncpp的Json::Value
参考链接: https://github.com/NickstaDB/SerializationDumper
用法:
JavaSerializationHandler jsonSerialize;
jsonSerialize.OpenSerializationBuffer(buf);
jsonSerialize.OpenSerializationFile(filepath);
dumpjson(jsonSerialize); //直接就是Json::Value的子类,可以直接按照json使用
说明:
如果对象是Object,那么会该Object的json节点会出现几个元素(使用前还是要校验一下存在与否):
"_desc" : 类的描述信息,包括类名、字段描述、父类信息等等
"_data" : 类的数据
"_block": 类的附加块数据,一些内置的java类型例如hashmap或者list等等会使用该字段,这里的数据一般需要二次整理,不要直接使用
"_array": 如果是Array类型数据例如java.util.ArrayList等,会出现该字段,类型是数组,数组的元素由_block字段中整理并保存到该字段下
"_hashmap":如果是java.util.HashMap类型数据会出现该字段,由_block字段中的数据整理并保存到该字段下
"_enum" : 暂时还没碰到过这个类型的数据样本,围观。。。
实例:
末尾部分。
*/
class JavaSerializationHandler : public Json::Value
{
/*******************
* Read a content element from the data stream.
*
* Could be any of:
* TC_OBJECT (0x73)
* TC_CLASS (0x76)
* TC_ARRAY (0x75)
* TC_STRING (0x74)
* TC_LONGSTRING (0x7c)
* TC_ENUM (0x7e)
* TC_CLASSDESC (0x72)
* TC_PROXYCLASSDESC (0x7d)
* TC_REFERENCE (0x71)
* TC_NULL (0x70)
* TC_EXCEPTION (0x7b)
* TC_RESET (0x79)
* TC_BLOCKDATA (0x77)
* TC_BLOCKDATALONG (0x7a)
******************/
enum classElementType
{
TC_NULL = 0x70,
TC_REFERENCE = 0x71,
TC_CLASSDESC = 0x72,
TC_OBJECT = 0x73,
TC_STRING = 0x74,
TC_ARRAY = 0x75,
TC_CLASS = 0x76,
TC_BLOCKDATA = 0x77,
TC_ENDBLOCKDATA = 0x78,
TC_RESET = 0x79,
TC_BLOCKDATALONG = 0x7a,
TC_EXCEPTION = 0x7b,
TC_LONGSTRING = 0x7c,
TC_ENUM = 0x7e,
TC_PROXYCLASSDESC = 0x7d
};
enum classDescFlags
{
SC_WRITE_METHOD = 0x01,
SC_SERIALIZABLE = 0x02,
SC_EXTERNALIZABLE = 0x04,
SC_BLOCK_DATA = 0x08
};
struct OBJECT_REF_DATA
{
uint32_t ref;
uint8_t type;
Json::Value data;
};
#ifndef _bswap_16
/* Swap bytes in 16 bit value. */
#define _bswap_16(x) \
((unsigned short int) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)))
#endif
#ifndef _bswap_32
/* Swap bytes in 32 bit value. */
#define _bswap_32(x) \
((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
#endif
#ifndef _bswap_64
/* Swap bytes in 64 bit value. */
# define _bswap_64(x) \
((((x) & 0xff00000000000000ull) >> 56) \
| (((x) & 0x00ff000000000000ull) >> 40) \
| (((x) & 0x0000ff0000000000ull) >> 24) \
| (((x) & 0x000000ff00000000ull) >> 8) \
| (((x) & 0x00000000ff000000ull) << 8) \
| (((x) & 0x0000000000ff0000ull) << 24) \
| (((x) & 0x000000000000ff00ull) << 40) \
| (((x) & 0x00000000000000ffull) << 56))
#endif
public:
JavaSerializationHandler() : m_refIndex(0x7e0000) {};
~JavaSerializationHandler() {};
template<typename _T>
bool OpenSerializationFile(const _T& filepath)
{
FFileStream infile(filepath);
m_bufstream = &infile;
bool ret = false;
#ifdef _DEBUG
ret = JavaSerializationParser(*this);
#else
try
{
ret = JavaSerializationParser(*this);
}
catch (...) {}
#endif // _DEBUG
return ret;
}
bool OpenSerializationBuffer(const std::string &buf)
{
FBufferStream stream(buf);
m_bufstream = &stream;
bool ret = false;
#ifdef _DEBUG
ret = JavaSerializationParser(*this);
#else
try
{
ret = JavaSerializationParser(*this);
}
catch (...) {}
#endif // _DEBUG
return ret;
}
private:
FStream* m_bufstream;
std::vector<OBJECT_REF_DATA> m_objectRefs;
uint32_t m_refIndex;
const char* getTypeString(uint8_t type)
{
//获取enum类型的字符串
switch (type)
{
case TC_NULL:
return "TC_NULL";
case TC_REFERENCE:
return "TC_REFERENCE";
case TC_CLASSDESC:
return "TC_CLASSDESC";
case TC_OBJECT:
return "TC_OBJECT";
case TC_STRING:
return "TC_STRING";
case TC_ARRAY:
return "TC_ARRAY";
case TC_CLASS:
return "TC_CLASS";
case TC_BLOCKDATA:
return "TC_BLOCKDATA";
case TC_ENDBLOCKDATA:
return "TC_ENDBLOCKDATA";
case TC_RESET:
return "TC_RESET";
case TC_BLOCKDATALONG:
return "TC_BLOCKDATALONG";
case TC_EXCEPTION:
return "TC_EXCEPTION";
case TC_LONGSTRING:
return "TC_LONGSTRING";
case TC_ENUM:
return "TC_ENUM";
}
return "UNKNOWN";
}
Json::Value getObjectByRef(uint32_t ref)
{
for (auto& obj : m_objectRefs)
{
if (obj.ref == ref)
{
#ifdef _DEBUG
// if (obj.type == TC_STRING || obj.type == TC_LONGSTRING)
// printf("get ref:0x%x, string:%s \n", ref, obj.data.asCString());
// else
// printf("get ref:0x%x, type:%s(%x) \n", ref, getTypeString(obj.type), obj.type);
#endif // _DEBUG
return obj.data;
break;
}
}
return {};
}
uint32_t setObjectRef(uint8_t type, const Json::Value& val)
{
m_objectRefs.emplace_back(OBJECT_REF_DATA{ m_refIndex , type, val });
#ifdef _DEBUG
// if (type == TC_STRING || type == TC_LONGSTRING)
// printf("new ref:0x%x, string:%s \n", m_refIndex, val.asCString());
// else
// printf("new ref:0x%x, type:%s(%x) \n", m_refIndex, getTypeString(type), type);
#endif // _DEBUG
return m_refIndex++;
}
void updateObjectRef(uint32_t ref, uint8_t type, const Json::Value& val)
{
for (auto& obj : m_objectRefs)
{
if (obj.ref == ref)
{
obj.type = type;
obj.data = val;
break;
}
}
}
std::string tohex(const std::string& data)
{
std::string strRet;
if (data.empty())
return strRet;
strRet.reserve(data.length() * 2);
const char* hex = "0123456789abcdef";
for (char ch : data)
{
strRet.push_back(hex[(unsigned char)ch >> 4]);
strRet.push_back(hex[(unsigned char)ch & 0xf]);
}
return strRet;
}
bool readReference(uint32_t& ref)
{
if (!m_bufstream->read_data(ref))
return false;
ref = _bswap_32(ref);
return true;
}
bool readUtf(std::string& ret)
{
uint16_t len;
if (!m_bufstream->read_data(len))
return false;
len = _bswap_16(len);
if (len && !m_bufstream->read_buffer(ret, len))
return false;
return true;
}
bool readLongUtf(std::string& ret)
{
uint64_t len;
if (!m_bufstream->read_data(len))
return false;
len = _bswap_64(len);
if (!m_bufstream->read_buffer(ret, (size_t)len))
return false;
return true;
}
bool readNewString(Json::Value& val)
{
uint8_t type;
if (!m_bufstream->read_data(type))
return false;
if (type == TC_STRING || type == TC_LONGSTRING || type == TC_REFERENCE)
return readContentElement(type, val);
//剩下的类型都不对
return false;
}
bool readNewArray(Json::Value& jsonarray)
{
Json::Value jsonDesc;
//Read the class data description to enable array elements to be read
if (!readClassDesc(jsonDesc))
return false;
if (!jsonDesc.isObject() || !jsonDesc["classname"].isString())
return false;
std::string str = jsonDesc["classname"].asString();
if (str.length() < 2 || str[0] != '[')
return false;
uint8_t type = str[1];
jsonarray["_desc"] = jsonDesc;
//索引值+1
int refindex = setObjectRef(TC_ARRAY, jsonarray);
//array size
uint32_t arraysize;
if (!m_bufstream->read_data(arraysize))
return false;
for (uint32_t i = 0; i < arraysize; i++)
{
if (!readFieldValue(type, jsonarray["_array"][i]))
return false;
}
//更新值
updateObjectRef(refindex, TC_ARRAY, jsonarray);
return true;
}
bool readFieldValue(int type, Json::Value& jsonvalue)
{
switch (type)
{
case 'B': //byte 1
uint8_t val;
if (!m_bufstream->read_data(val))
return false;
jsonvalue = val;
break;
case 'C': //char java里面的char占用2字节
case 'S': //short
{
uint16_t val;
if (!m_bufstream->read_data(val))
return false;
jsonvalue = _bswap_16(val);
break;
}
case 'D': //double
{
uint64_t val;
if (!m_bufstream->read_data(val))
return false;
val = _bswap_64(val);
jsonvalue = *(double*)&val;
break;
}
case 'F': //float
{
uint32_t val;
if (!m_bufstream->read_data(val))
return false;
val = _bswap_32(val);
jsonvalue = *(float*)&val;
break;
}
case 'I': //int
{
uint32_t val;
if (!m_bufstream->read_data(val))
return false;
jsonvalue = (int32_t)_bswap_32(val);
break;
}
case 'J': //long
{
uint64_t val;
if (!m_bufstream->read_data(val))
return false;
jsonvalue = (int64_t)_bswap_64(val);
break;
}
case 'Z': //boolean
{
uint8_t val;
if (!m_bufstream->read_data(val))
return false;
if (val)
jsonvalue = true;
else
jsonvalue = false;
break;
}
case '[': //array
case 'L': //object
if (!readContentElement(jsonvalue))
return false;
break;
default: //Unknown field type
printf("unknown filed type: %c\n", type);
return false;
}
return true;
}
bool readClassAnnotation(Json::Value& jsonret)
{
//classAnnotation
int index = 0;
while (true)
{
uint8_t type;
if (!m_bufstream->read_data(type))
return false;
if (type == TC_ENDBLOCKDATA)
break;
if (!readContentElement(type, jsonret[index]))
return false;
index++;
}
return true;
}
bool readNewClassDesc(Json::Value& jsonret)
{
//由于desc很长很长,先占个坑把ref的index占了
uint32_t refindex = setObjectRef(TC_CLASSDESC, jsonret);
//className
std::string className;
if (!readUtf(className))
return false;
if (className.empty())
{
printf("Error: class name is empty.\n");
return false;
}
jsonret["classname"] = className;
//serialVersionUID 固定8字节
std::string serialVersionUID;
if (!m_bufstream->read_buffer(serialVersionUID, 8))
return false;
jsonret["uid"] = tohex(serialVersionUID);
//classDescFlags
uint8_t classflags;
if (!m_bufstream->read_data(classflags))
return false;
////Validate classDescFlags
if ((classflags & 0x02) == 0x02)
{
if ((classflags & 0x04) == 0x04)
{
printf("Error: Illegal classDescFlags, SC_SERIALIZABLE is not compatible with SC_EXTERNALIZABLE. \n");
return false;
}
if ((classflags & 0x08) == 0x08)
{
printf("Error: Illegal classDescFlags, SC_SERIALIZABLE is not compatible with SC_BLOCK_DATA. \n");
return false;
}
}
else if ((classflags & 0x04) == 0x04)
{
if ((classflags & 0x01) == 0x01)
{
printf("Error: Illegal classDescFlags, SC_EXTERNALIZABLE is not compatible with SC_WRITE_METHOD.\n");
return false;
}
}
else if (classflags != 0x00)
{
printf("Error: Illegal classDescFlags, must include either SC_SERIALIZABLE or SC_EXTERNALIZABLE. \n");
return false;
}
jsonret["flags"] = classflags;
//read fields
uint16_t fieldcount;
if (!m_bufstream->read_data(fieldcount))
return false;
fieldcount = _bswap_16(fieldcount);
jsonret["fields"].resize(0);
for (uint16_t i = 0; i < fieldcount; i++)
{
uint8_t fieldtype;
if (!m_bufstream->read_data(fieldtype))
return false;
jsonret["fields"][i]["type"] = fieldtype;
std::string fieldname;
if (!readUtf(fieldname))
return false;
if (fieldname.empty())
{
printf("Error: field name is empty.\n");
//return false;
}
jsonret["fields"][i]["name"] = fieldname;
if (fieldtype == '[' || fieldtype == 'L')
{
if (!readNewString(jsonret["fields"][i]["classname"]))
return false;
}
}
//ClassAnnotation
if (!readClassAnnotation(jsonret["annotation"]))
return false;
//SuperClassDesc ???
if (!readClassDesc(jsonret["superclass"]))
return false;
//更新refs
updateObjectRef(refindex, TC_CLASSDESC, jsonret);
return true;
}
bool readNewProxyClassDesc(Json::Value& jsonret)
{
//由于desc很长很长,先占个坑把ref的index占了
uint32_t refindex = setObjectRef(TC_PROXYCLASSDESC, jsonret);
uint32_t count;
if (!m_bufstream->read_data(count))
return false;
count = _bswap_32(count);
//proxyInterfaceNames
for (uint32_t i = 0; i < count; i++)
{
std::string classname;
if (!readUtf(classname))
return false;
jsonret["proxyclass"][i] = classname;
}
//ClassAnnotation
if (!readClassAnnotation(jsonret["annotation"]))
return false;
//SuperClassDesc ???
if (!readClassDesc(jsonret["superclass"]))
return false;
//更新refs
updateObjectRef(refindex, TC_PROXYCLASSDESC, jsonret);
return true;
}
//读取class的描述信息
bool readClassDesc(Json::Value& jsonClassDesc)
{
uint8_t t;
if (!m_bufstream->read_data(t))
return false;
if (t == TC_CLASSDESC || t == TC_PROXYCLASSDESC || t == TC_REFERENCE || t == TC_NULL)
return readContentElement(t, jsonClassDesc);
return false;
}
bool readClassData(const Json::Value& classDesc, Json::Value& jsonret)
{
//通过遍历递归的手法 让superclass排到读取的前面去
if (classDesc["superclass"].isObject() && classDesc["superclass"]["classname"].isString())
{
//递归走起
if (!readClassData(classDesc["superclass"], jsonret["_super"]))
return false;
}
//搞自己的吧
//仅支持标准TC_CLASSDESC TC_PROXYCLASSDESC暂无数据没办法测试研究。。。
assert(classDesc["classname"].isString());
assert(classDesc["fields"].isArray());
assert(classDesc["flags"].isInt());
if (!classDesc["classname"].isString())
{
printf("Error:no class name.\n");
return false;
}
if (!classDesc["fields"].isArray())
{
printf("Error:no fields.\n");
return false;
}
if (!classDesc["flags"].isInt())
{
printf("Error:no flags.\n");
return false;
}
int flags = classDesc["flags"].asInt();
jsonret["_desc"] = classDesc;
if (flags & SC_SERIALIZABLE)
{
//读取字段数据
size_t fieldscount = classDesc["fields"].size();
for (size_t i = 0; i < fieldscount; i++)
{
const Json::Value& jsonField = classDesc["fields"][i];
if (!readFieldValue(jsonField["type"].asInt(), jsonret["_data"][jsonField["name"].asString()]))
return false;
}
}
bool hasBlockData = false;
if ((flags & SC_SERIALIZABLE) && (flags & SC_WRITE_METHOD))
hasBlockData = true;
if (flags & SC_EXTERNALIZABLE)
{
if (flags & SC_BLOCK_DATA)
{
hasBlockData = true;
}
else
{
printf("Unable to parse externalContents for protocol version 1.\n");
return false;
}
}
if (hasBlockData)
{
if (!readClassAnnotation(jsonret["_block"]))
return false;
}
//额外处理几种类型的显示
//"java.util.HashMap"
if (classDesc["classname"].asString() == "java.util.HashMap" && jsonret["_block"].isArray())
{
jsonret["_hashmap"].resize(0);
//hashmap 在block里面第0个疑似是hashmap的size(),直接无视,解析内容
//内容是size;key-value;key-value;key-value;
size_t blockcount = jsonret["_block"].size();
if (blockcount % 2) //第一块是size 后面是kv对
{
size_t kvcount = blockcount / 2;
//printf("Hashmap size: %d\n", kvcount);
for (size_t i = 0; i < kvcount; i++)
{
//key
Json::Value key;
const Json::Value& keytmp = jsonret["_block"][i * 2 + 1];
if (keytmp.isObject() && keytmp["_data"].isObject() && !keytmp["_data"]["value"].isNull())
key = keytmp["_data"]["value"];
else
key = keytmp;
//value
const Json::Value& valuetmp = jsonret["_block"][i * 2 + 2];
if (valuetmp.isObject() && valuetmp["_data"].isObject() && !valuetmp["_data"]["value"].isNull())
jsonret["_hashmap"][i][key.asString()] = valuetmp["_data"]["value"];
else
jsonret["_hashmap"][i][key.asString()] = valuetmp;
#ifdef _DEBUG
//printf("key:%s, value:%s\n", Json2String(key).c_str(), Json2String(jsonret["_hashmap"][i][key.asString()]).c_str());
#endif // _DEBUG
}
}
}
//java.util.ArrayList
if (classDesc["classname"].asString() == "java.util.ArrayList" && jsonret["_block"].isArray())
{
jsonret["_array"].resize(0);
//_data里面有一个"size": 1表示的就是size
//blockdata里面第一个元素应该也是长度,直接无视,读取所有blockdata
size_t blockcount = jsonret["_block"].size();
if (blockcount > 1)
{
blockcount--; //将第一个元素去掉
for (size_t i = 0; i < blockcount; i++)
{
Json::Value& datatmp = jsonret["_block"][i + 1];
if (datatmp.isObject() && !datatmp["_data"].isNull())
jsonret["_array"][i] = datatmp["_data"];
else
jsonret["_array"][i] = datatmp;
}
}
}
//其他的类型待补充
//...
return true;
}
bool readNewObject(Json::Value& jsonret)
{
//printf("TC_OBJECT\n");
//读取类描述
Json::Value classDesc;
if (!readClassDesc(classDesc))
return false;
//这中间要让索引值加1
uint32_t refindex = setObjectRef(TC_OBJECT, jsonret);
//读取值
if (!readClassData(classDesc, jsonret))
return false;
//更新值
updateObjectRef(refindex, TC_OBJECT, jsonret);
return true;
}
bool readNewClass(Json::Value& jsonret)
{
//printf("TC_CLASS\n");
Json::Value classDesc;
if (!readClassDesc(classDesc))
return false;
assert(classDesc["classname"].isString());
if (!classDesc["classname"].isString())
{
//printf("Error:no class name.\n");
return false;
}
jsonret["_desc"] = classDesc;
//增加引用 不知道还能干啥
m_refIndex++;
return true;
}
bool readNewEnum(Json::Value& jsonret)
{
//printf("TC_ENUM\n");
Json::Value classDesc;
if (!readClassDesc(classDesc))
return false;
assert(classDesc["classname"].isString());
if (!classDesc["classname"].isString())
{
printf("Error:no class name.\n");
return false;
}
//先增加引用
int refindex = setObjectRef(TC_ENUM, jsonret);
jsonret["_desc"] = classDesc;
//enumConstantName ???
if (!readNewString(jsonret["_enum"]))
return false;
//更新引用的值
updateObjectRef(refindex, TC_ENUM, jsonret);
return true;
}
bool readBlockData(Json::Value& jsonret)
{
//printf("TC_BLOCKDATA\n");
uint8_t len;
if (!m_bufstream->read_data(len))
return false;
if (len)
{
std::string block;
if (!m_bufstream->read_buffer(block, len))
return false;
jsonret = tohex(block);
}
else
{
jsonret = "";
}
return true;
}
bool readBlockDataLong(Json::Value& jsonret)
{
//printf("TC_BLOCKDATALONG\n");
uint32_t len;
if (!m_bufstream->read_data(len))
return false;
len = _bswap_32(len);
if (len)
{
std::string block;
if (!m_bufstream->read_buffer(block, len))
return false;
jsonret = tohex(block);
}
else
{
jsonret = "";
}
return true;
}
bool readContentElement(uint8_t type, Json::Value& jsonret)
{
switch (type)
{
case TC_OBJECT:
if (!readNewObject(jsonret))
return false;
break;
case TC_CLASS:
if (!readNewClass(jsonret))
return false;
break;
case TC_ARRAY:
if (!readNewArray(jsonret))
return false;
break;
case TC_STRING:
{
std::string val;
if (!readUtf(val))
return false;
jsonret = val;
setObjectRef(TC_STRING, jsonret);
break;
}
case TC_LONGSTRING:
{
std::string val;
if (!readLongUtf(val))
return false;
jsonret = val;
setObjectRef(TC_STRING, jsonret);
break;
}
case TC_ENUM:
if (!readNewEnum(jsonret))
return false;
break;
case TC_CLASSDESC:
if (!readNewClassDesc(jsonret))
return false;
break;
case TC_PROXYCLASSDESC:
if (!readNewProxyClassDesc(jsonret))
return false;
break;
case TC_REFERENCE:
uint32_t ref;
if (!readReference(ref))
return false;
jsonret = getObjectByRef(ref);
break;
case TC_NULL:
jsonret = NULL;
break;
// case TC_EXCEPTION:
// printf("TC_EXCEPTION\n");
// break;
// case TC_RESET:
// printf("TC_RESET\n");
// break;
case TC_BLOCKDATA:
if (!readBlockData(jsonret))
return false;
break;
case TC_BLOCKDATALONG:
if (!readBlockDataLong(jsonret))
return false;
break;
default:
printf("Unknown type - %x\n", type);
break;
}
return true;
}
bool readContentElement(Json::Value& jsonret)
{
uint8_t t;
if (!m_bufstream->read_data(t))
return false;
return readContentElement(t, jsonret);
}
bool JavaSerializationParser(Json::Value& jsonret)
{
uint8_t b1, b2;
//读取文件头
if (!m_bufstream->read_data(b1))
return false;
if (b1 != 0xac)
{
switch (b1) {
case 0x50:
printf("RMI Call - 0x50 \n");
break;
case 0x51:
printf("RMI ReturnData - 0x51 \n");
break;
case 0x52:
printf("RMI Ping - 0x52 \n");
break;
case 0x53:
printf("RMI PingAck - 0x53 \n");
break;
case 0x54:
printf("RMI DgcAck - 0x54 \n");
break;
default:
printf("Unknown RMI packet type - 0x%x \n" + b1);
break;
}
//不是0xac开头的 再读取一次
if (!m_bufstream->read_data(b1))
return false;
}
if (!m_bufstream->read_data(b2))
return false;
//校验文件头
printf("STREAM_MAGIC - %x %x\n", b1, b2);
if (b1 != 0xac || b2 != 0xed)
{
printf("Invalid STREAM_MAGIC, should be ac ed \n");
return false;
}
//校验版本
if (!m_bufstream->read_data(b1))
return false;
if (!m_bufstream->read_data(b2))
return false;
printf("STREAM_VERSION - %x %x\n", b1, b2);
if (b1 != 0x00 || b2 != 0x05)
{
printf("Invalid STREAM_VERSION, should be 00 05 \n");
return false;
}
//解析内容了
int index = 0;
while (true)
{
Json::Value value;
if (!readContentElement(value))
{
if (!value.isNull())
{
if (index == 0)
jsonret = value;
else
jsonret[index] = value;
return false;
}
}
if (m_bufstream->eof())
break;
//后面还有
jsonret[index] = value;
index++;
}
return true;
}
};
/*
//实例1 普通的对象 使用_data
{
"_data":
{
"B_points": 0,
"account_desc": "E会员",
"account_level": 5,
"android_url": "",
"auth_token": "GgMBu55DmpL8hm7HNRsg",
"avatar": "https://ugc.bthhotels.com/avatar/images/default_avatar.png!a160",
"balance": 0,
"birth": "1995/01/12",
"btn_text": "",
"can_update_avatar": false,
"carbon_points": 0,
"card_balance": "0",
"card_code": "",
"code": "100000138749707",
"ctf_code": "412702199601028052",
"ctf_type": "ID",
"desc": "",
"down_days_left": 0,
"down_expire_date": "2023-04-08",
"email": "",
"gift_switch": true,
"growth_value": 0,
"keep_level_growth_value": 0,
"keep_level_score": "",
"level_up_growth_value": 1000,
"lvl_exp_text": "",
"name": "张三",
"new_balance": "0",
"new_red_packet": "0",
"next_account_desc": "银会员",
"next_level_nights": 3,
"nights": 0,
"phone": "136****7271",
"points": 0,
"red_packet": 0,
"score_speed_times": 1.0,
"tags": "[\"SL01\",\"E06\"]",
"title": "",
"user_markers": "[]"
},
"_desc":
{
"annotation": null,
"classname": "com.ziipin.homeinn.model.UserInfo",
"fields": [
{
"name": "B_points",
"type": 73
},
{
"name": "account_level",
"type": 73
},
{
"name": "balance",
"type": 73
},
{
"name": "can_update_avatar",
"type": 90
},
{
"name": "carbon_points",
"type": 73
},
{
"name": "down_days_left",
"type": 73
},
{
"name": "gift_switch",
"type": 90
},
{
"name": "growth_value",
"type": 73
},
{
"name": "keep_level_growth_value",
"type": 73
},
{
"name": "level_up_growth_value",
"type": 73
},
{
"name": "next_level_nights",
"type": 73
},
{
"name": "nights",
"type": 73
},
{
"name": "points",
"type": 73
},
{
"name": "red_packet",
"type": 73
},
{
"name": "score_speed_times",
"type": 70
},
{
"classname": "Ljava/lang/String;",
"name": "account_desc",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "android_url",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "auth_token",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "avatar",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "birth",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "btn_text",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "card_balance",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "card_code",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "code",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "ctf_code",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "ctf_type",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "desc",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "down_expire_date",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "email",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "keep_level_score",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "lvl_exp_text",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "name",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "new_balance",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "new_red_packet",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "next_account_desc",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "phone",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "tags",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "title",
"type": 76
},
{
"classname": "Ljava/lang/String;",
"name": "user_markers",
"type": 76
}],
"flags": 2,
"superclass": 0,
"uid": "fb74abdfc6ffaf03"
}
}
实例2:hashmap类的解析,看_hashmap字段
{
"_block": [
"0000000800000005",
{
"_data": {
"value": 98305
},
"_desc": {
"annotation": null,
"classname": "java.lang.Integer",
"fields": [
{
"name": "value",
"type": 73
}
],
"flags": 2,
"superclass": {
"annotation": null,
"classname": "java.lang.Number",
"fields": [],
"flags": 2,
"superclass": 0,
"uid": "86ac951d0b94e08b"
},
"uid": "12e2a0a4f7818738"
},
"_super": {
"_desc": {
"annotation": null,
"classname": "java.lang.Number",
"fields": [],
"flags": 2,
"superclass": 0,
"uid": "86ac951d0b94e08b"
}
}
},
{
"_data": {
"value": true
},
"_desc": {
"annotation": null,
"classname": "java.lang.Boolean",
"fields": [
{
"name": "value",
"type": 90
}
],
"flags": 2,
"superclass": 0,
"uid": "cd207280d59cfaee"
}
},
{
"_data": {
"value": 256
},
"_desc": {
"annotation": null,
"classname": "java.lang.Integer",
"fields": [
{
"name": "value",
"type": 73
}
],
"flags": 2,
"superclass": {
"annotation": null,
"classname": "java.lang.Number",
"fields": [],
"flags": 2,
"superclass": 0,
"uid": "86ac951d0b94e08b"
},
"uid": "12e2a0a4f7818738"
},
"_super": {
"_desc": {
"annotation": null,
"classname": "java.lang.Number",
"fields": [],
"flags": 2,
"superclass": 0,
"uid": "86ac951d0b94e08b"
}
}
},
"A86880902494769",
{
"_data": {
"value": 259
},
"_desc": {
"annotation": null,
"classname": "java.lang.Integer",
"fields": [
{
"name": "value",
"type": 73
}
],
"flags": 2,
"superclass": {
"annotation": null,
"classname": "java.lang.Number",
"fields": [],
"flags": 2,
"superclass": 0,
"uid": "86ac951d0b94e08b"
},
"uid": "12e2a0a4f7818738"
},
"_super": {
"_desc": {
"annotation": null,
"classname": "java.lang.Number",
"fields": [],
"flags": 2,
"superclass": 0,
"uid": "86ac951d0b94e08b"
}
}
},
"OPPOOPPO R7sPlus: fp asimd evtstrm aes pmull sha1 sha2 crc32: AArch64 Processor rev 4 (aarch64): 8: Qualcomm Technologies, Inc MSM8939: null",
{
"_data": {
"value": 94209
},
"_desc": {
"annotation": null,
"classname": "java.lang.Integer",
"fields": [
{
"name": "value",
"type": 73
}
],
"flags": 2,
"superclass": {
"annotation": null,
"classname": "java.lang.Number",
"fields": [],
"flags": 2,
"superclass": 0,
"uid": "86ac951d0b94e08b"
},
"uid": "12e2a0a4f7818738"
},
"_super": {
"_desc": {
"annotation": null,
"classname": "java.lang.Number",
"fields": [],
"flags": 2,
"superclass": 0,
"uid": "86ac951d0b94e08b"
}
}
},
{
"_data": {
"value": 0
},
"_desc": {
"annotation": null,
"classname": "java.lang.Integer",
"fields": [
{
"name": "value",
"type": 73
}
],
"flags": 2,
"superclass": {
"annotation": null,
"classname": "java.lang.Number",
"fields": [],
"flags": 2,
"superclass": 0,
"uid": "86ac951d0b94e08b"
},
"uid": "12e2a0a4f7818738"
},
"_super": {
"_desc": {
"annotation": null,
"classname": "java.lang.Number",
"fields": [],
"flags": 2,
"superclass": 0,
"uid": "86ac951d0b94e08b"
}
}
},
{
"_data": {
"value": 258
},
"_desc": {
"annotation": null,
"classname": "java.lang.Integer",
"fields": [
{
"name": "value",
"type": 73
}
],
"flags": 2,
"superclass": {
"annotation": null,
"classname": "java.lang.Number",
"fields": [],
"flags": 2,
"superclass": 0,
"uid": "86ac951d0b94e08b"
},
"uid": "12e2a0a4f7818738"
},
"_super": {
"_desc": {
"annotation": null,
"classname": "java.lang.Number",
"fields": [],
"flags": 2,
"superclass": 0,
"uid": "86ac951d0b94e08b"
}
}
},
"868809024947694"
],
"_data": {
"loadFactor": 0.75
},
"_desc": {
"annotation": null,
"classname": "java.util.HashMap",
"fields": [
{
"name": "loadFactor",
"type": 70
}
],
"flags": 3,
"superclass": 0,
"uid": "0507dac1c31660d1"
},
"_hashmap": [
{
"98305": true
},
{
"256": "A86880902494769"
},
{
"259": "OPPOOPPO R7sPlus: fp asimd evtstrm aes pmull sha1 sha2 crc32: AArch64 Processor rev 4 (aarch64): 8: Qualcomm Technologies, Inc MSM8939: null"
},
{
"94209": 0
},
{
"258": "868809024947694"
}
]
}
*/
2025/6/25 | Tags:Java,Serialize,SerializationDumper | C/C++代码 | 查看评论(0)