All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.redkale.convert.json.JsonReader Maven / Gradle / Ivy

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.redkale.convert.json;

import org.redkale.convert.*;
import static org.redkale.convert.Reader.*;
import org.redkale.util.*;

/**
 * JSON数据源
 *
 * 

* 详情见: https://redkale.org * * @author zhangjx */ public class JsonReader extends Reader { protected int position = -1; private char[] text; private int limit; public static ObjectPool createPool(int max) { return new ObjectPool<>(max, (Object... params) -> new JsonReader(), null, JsonReader::recycle); } public JsonReader() { } public JsonReader(String json) { setText(Utility.charArray(json)); } public JsonReader(char[] text) { setText(text, 0, text.length); } public JsonReader(char[] text, int start, int len) { setText(text, start, len); } public final void setText(String text) { setText(Utility.charArray(text)); } public final void setText(char[] text) { setText(text, 0, text.length); } public final void setText(char[] text, int start, int len) { this.text = text; this.position = start - 1; this.limit = start + len - 1; } protected boolean recycle() { this.position = -1; this.limit = -1; this.text = null; return true; } public void close() { this.recycle(); } /** * 找到指定的属性值 例如: {id : 1, data : { name : 'a', items : [1,2,3]}} seek('data.items') 直接跳转到 [1,2,3]; * * @param key 指定的属性名 */ public final void seek(String key) { if (key == null || key.length() < 1) return; final String[] keys = key.split("\\."); nextGoodChar(); //读掉 { [ for (String key1 : keys) { while (this.hasNext()) { String field = this.readSmallString(); readBlank(); if (key1.equals(field)) break; skipValue(); } } } /** * 跳过属性的值 */ @Override public final void skipValue() { final char ch = nextGoodChar(); switch (ch) { case '"': case '\'': backChar(ch); readString(); break; case '{': while (hasNext()) { this.readSmallString(); //读掉field this.readBlank(); this.skipValue(); } break; case '[': while (hasNext()) { this.skipValue(); } break; default: char c; for (;;) { c = nextChar(); if (c <= ' ') return; if (c == '}' || c == ']' || c == ',' || c == ':') { backChar(c); return; } } } } /** * 读取下一个字符, 不跳过空白字符 * * @return 空白字符或有效字符 */ protected char nextChar() { return this.text[++this.position]; } /** * 跳过空白字符, 返回一个非空白字符 * * @return 有效字符 */ protected char nextGoodChar() { char c = nextChar(); if (c > ' ') return c; for (;;) { c = nextChar(); if (c > ' ') return c; } } /** * 回退最后读取的字符 * * @param ch 后退的字符 */ protected void backChar(char ch) { this.position--; } /** * 判断下一个非空白字符是否为{ * * @param clazz 类名 * * @return 返回 null 表示对象为null, 返回空字符串表示当前class与返回的class一致,返回非空字符串表示class是当前class的子类。 */ @Override public String readObjectB(final Class clazz) { this.fieldIndex = 0; //必须要重置为0 char ch = this.text[++this.position]; if (ch == '{') return ""; if (ch <= ' ') { for (;;) { ch = this.text[++this.position]; if (ch > ' ') break; } if (ch == '{') return ""; } if (ch == 'n' && text[++position] == 'u' && text[++position] == 'l' && text[++position] == 'l') return null; if (ch == 'N' && text[++position] == 'U' && text[++position] == 'L' && text[++position] == 'L') return null; throw new ConvertException("a json object text must begin with '{' (position = " + position + ") but '" + ch + "' in (" + new String(this.text) + ")"); } @Override public final void readObjectE(final Class clazz) { } /** * 判断下一个非空白字符是否为{ * * @param member DeMember * @param keydecoder Decodeable * * @return SIGN_NOLENGTH 或 SIGN_NULL */ @Override public final int readMapB(DeMember member, Decodeable keydecoder) { return readArrayB(member, keydecoder); } @Override public final void readMapE() { } /** * 判断下一个非空白字符是否为[ * * @param member DeMember * @param decoder Decodeable * * @return SIGN_NOLENGTH 或 SIGN_NULL */ @Override public int readArrayB(DeMember member, Decodeable decoder) { char ch = this.text[++this.position]; if (ch == '[') return SIGN_NOLENGTH; if (ch == '{') return SIGN_NOLENGTH; if (ch <= ' ') { for (;;) { ch = this.text[++this.position]; if (ch > ' ') break; } if (ch == '[') return SIGN_NOLENGTH; if (ch == '{') return SIGN_NOLENGTH; } if (ch == 'n' && text[++position] == 'u' && text[++position] == 'l' && text[++position] == 'l') return SIGN_NULL; if (ch == 'N' && text[++position] == 'U' && text[++position] == 'L' && text[++position] == 'L') return SIGN_NULL; throw new ConvertException("a json array text must begin with '[' (position = " + position + ") but '" + ch + "' in (" + new String(this.text) + ")"); } @Override public final void readArrayE() { } /** * 判断下一个非空白字符是否: */ @Override public void readBlank() { char ch = this.text[++this.position]; if (ch == ':') return; if (ch <= ' ') { for (;;) { ch = this.text[++this.position]; if (ch > ' ') break; } if (ch == ':') return; } throw new ConvertException("'" + new String(text) + "'expected a ':' but '" + ch + "'(position = " + position + ") in (" + new String(this.text) + ")"); } @Override public int position() { return this.position; } @Override public int readMemberContentLength(DeMember member, Decodeable decoder) { return -1; } /** * 判断对象是否存在下一个属性或者数组是否存在下一个元素 * * @param startPosition 起始位置 * @param contentLength 内容大小, 不确定的传-1 * * @return 是否存在 */ @Override public boolean hasNext(int startPosition, int contentLength) { char ch = this.text[++this.position]; if (ch == ',') return true; if (ch == '}' || ch == ']') return false; if (ch <= ' ') { for (;;) { ch = this.text[++this.position]; if (ch > ' ') break; } if (ch == ',') return true; if (ch == '}' || ch == ']') return false; } this.position--; // { [ 交由 readObjectB 或 readMapB 或 readArrayB 读取 return true; } @Override public final String readClassName() { return null; } @Override public String readSmallString() { final int eof = this.limit; if (this.position == eof) return null; final char[] text0 = this.text; int currpos = this.position; char ch = text0[++currpos]; if (ch <= ' ') { for (;;) { ch = text0[++currpos]; if (ch > ' ') break; } } if (ch == '"' || ch == '\'') { final char quote = ch; final int start = currpos + 1; for (;;) { ch = text0[++currpos]; if (ch == '\\') { this.position = currpos - 1; return readEscapeValue(quote, start); } else if (ch == quote) { break; } } this.position = currpos; char[] chs = new char[currpos - start]; System.arraycopy(text0, start, chs, 0, chs.length); return new String(chs); } else { int start = currpos; for (;;) { if (currpos == eof) break; ch = text0[++currpos]; if (ch == ',' || ch == ']' || ch == '}' || ch <= ' ' || ch == ':') break; } int len = currpos - start; if (len < 1) { this.position = currpos; return String.valueOf(ch); } this.position = currpos - 1; if (len == 4 && text0[start] == 'n' && text0[start + 1] == 'u' && text0[start + 2] == 'l' && text0[start + 3] == 'l') return null; return new String(text0, start, len); } } /** * 读取一个int值 * * @return int值 */ @Override public int readInt() { final char[] text0 = this.text; final int eof = this.limit; int currpos = this.position; char firstchar = text0[++currpos]; if (firstchar <= ' ') { for (;;) { firstchar = text0[++currpos]; if (firstchar > ' ') break; } } boolean quote = false; if (firstchar == '"' || firstchar == '\'') { quote = true; firstchar = text0[++currpos]; if (firstchar <= ' ') { for (;;) { firstchar = text0[++currpos]; if (firstchar > ' ') break; } } if (firstchar == '"' || firstchar == '\'') { this.position = currpos; return 0; } } int value = 0; final boolean negative = firstchar == '-'; if (!negative) { if (firstchar < '0' || firstchar > '9') throw new ConvertException("illegal escape(" + firstchar + ") (position = " + currpos + ") in (" + new String(this.text) + ")"); value = firstchar - '0'; } for (;;) { if (currpos == eof) break; char ch = text0[++currpos]; int val = digits[ch]; if (quote && val == -3) continue; if (val <= -3) break; if (val == -1) throw new ConvertException("illegal escape(" + ch + ") (position = " + currpos + ") but '" + ch + "' in (" + new String(this.text) + ")"); if (val != -2) value = value * 10 + val; } this.position = currpos - 1; return negative ? -value : value; } /** * 读取一个long值 * * @return long值 */ @Override public long readLong() { final char[] text0 = this.text; final int eof = this.limit; int currpos = this.position; char firstchar = text0[++currpos]; if (firstchar <= ' ') { for (;;) { firstchar = text0[++currpos]; if (firstchar > ' ') break; } } boolean quote = false; if (firstchar == '"' || firstchar == '\'') { quote = true; firstchar = text0[++currpos]; if (firstchar <= ' ') { for (;;) { firstchar = text0[++currpos]; if (firstchar > ' ') break; } } if (firstchar == '"' || firstchar == '\'') { this.position = currpos; return 0L; } } long value = 0; final boolean negative = firstchar == '-'; if (!negative) { if (firstchar < '0' || firstchar > '9') throw new ConvertException("illegal escape(" + firstchar + ") (position = " + currpos + ") in (" + new String(this.text) + ")"); value = firstchar - '0'; } for (;;) { if (currpos == eof) break; char ch = text0[++currpos]; int val = digits[ch]; if (quote && val == -3) continue; if (val <= -3) break; if (val == -1) throw new ConvertException("illegal escape(" + ch + ") (position = " + currpos + ") but '" + ch + "' in (" + new String(this.text) + ")"); if (val != -2) value = value * 10 + val; } this.position = currpos - 1; return negative ? -value : value; } @Override public final DeMember readFieldName(final DeMember[] members) { final String exceptedfield = this.readSmallString(); if (exceptedfield == null) return null; final int len = members.length; if (this.fieldIndex >= len) this.fieldIndex = 0; for (int k = this.fieldIndex; k < len; k++) { if (exceptedfield.equals(members[k].getAttribute().field())) { this.fieldIndex = k; return members[k]; } } for (int k = 0; k < this.fieldIndex; k++) { if (exceptedfield.equals(members[k].getAttribute().field())) { this.fieldIndex = k; return members[k]; } } return null; //if (result == null && len == 1 && text0[start] == '@') return REFER; } //------------------------------------------------------------ @Override public final boolean readBoolean() { return "true".equalsIgnoreCase(this.readSmallString()); } @Override public final byte readByte() { return (byte) readInt(); } @Override public final byte[] readByteArray() { int len = readArrayB(null, null); int contentLength = -1; if (len == Reader.SIGN_NULL) return null; if (len == Reader.SIGN_NOLENBUTBYTES) { contentLength = readMemberContentLength(null, null); len = Reader.SIGN_NOLENGTH; } if (len == Reader.SIGN_NOLENGTH) { int size = 0; byte[] data = new byte[8]; int startPosition = position(); while (hasNext(startPosition, contentLength)) { if (size >= data.length) { byte[] newdata = new byte[data.length + 4]; System.arraycopy(data, 0, newdata, 0, size); data = newdata; } data[size++] = readByte(); } readArrayE(); byte[] newdata = new byte[size]; System.arraycopy(data, 0, newdata, 0, size); return newdata; } else { byte[] values = new byte[len]; for (int i = 0; i < values.length; i++) { values[i] = readByte(); } readArrayE(); return values; } } @Override public final char readChar() { return (char) readInt(); } @Override public final short readShort() { return (short) readInt(); } @Override public final float readFloat() { String chars = readSmallString(); if (chars != null) chars = chars.trim(); if (chars == null || chars.isEmpty()) return 0.f; return Float.parseFloat(chars); } @Override public final double readDouble() { String chars = readSmallString(); if (chars != null) chars = chars.trim(); if (chars == null || chars.isEmpty()) return 0.0; return Double.parseDouble(chars); } /** * 读取字符串, 必须是"或者'包围的字符串值 * * @return String值 */ @Override public String readString() { final char[] text0 = this.text; int currpos = this.position; char expected = text0[++currpos]; if (expected <= ' ') { for (;;) { expected = text0[++currpos]; if (expected > ' ') break; } } if (expected != '"' && expected != '\'') { if (expected == 'n' && text0.length > currpos + 3 && (text0[1 + currpos] == 'u' && text0[2 + currpos] == 'l' && text0[3 + currpos] == 'l')) { if (text0[++currpos] == 'u' && text0[++currpos] == 'l' && text0[++currpos] == 'l') { this.position = currpos; if (text0.length > currpos + 4) { char ch = text0[currpos + 1]; if (ch == ',' || ch <= ' ' || ch == '}' || ch == ']' || ch == ':') return null; final int start = currpos - 3; for (;;) { if (currpos >= text0.length) break; ch = text0[currpos]; if (ch == ',' || ch <= ' ' || ch == '}' || ch == ']' || ch == ':') break; currpos++; } if (currpos == start) throw new ConvertException("expected a string after a key but '" + text0[position] + "' (position = " + position + ") in (" + new String(this.text) + ")"); this.position = currpos - 1; return new String(text0, start, currpos - start); } else { return null; } } } else { final int start = currpos; for (;;) { if (currpos >= text0.length) break; char ch = text0[currpos]; if (ch == ',' || ch <= ' ' || ch == '}' || ch == ']' || ch == ':') break; currpos++; } if (currpos == start) throw new ConvertException("expected a string after a key but '" + text0[position] + "' (position = " + position + ") in (" + new String(this.text) + ")"); this.position = currpos - 1; return new String(text0, start, currpos - start); } this.position = currpos; throw new ConvertException("expected a ':' after a key but '" + text0[position] + "' (position = " + position + ") in (" + new String(this.text) + ")"); } final int start = ++currpos; for (;;) { char ch = text0[currpos]; if (ch == expected) { break; } else if (ch == '\\') { this.position = currpos - 1; return readEscapeValue(expected, start); } currpos++; } this.position = currpos; return new String(text0, start, currpos - start); } private String readEscapeValue(final char expected, int start) { StringBuilder array = new StringBuilder(); final char[] text0 = this.text; int pos = this.position; array.append(text0, start, pos + 1 - start); char c; for (;;) { c = text0[++pos]; if (c == expected) { this.position = pos; return array.toString(); } else if (c == '\\') { c = text0[++pos]; switch (c) { case '"': case '\'': case '\\': case '/': array.append(c); break; case 'n': array.append('\n'); break; case 'r': array.append('\r'); break; case 'u': array.append((char) Integer.parseInt(new String(new char[]{text0[++pos], text0[++pos], text0[++pos], text0[++pos]}), 16)); break; case 't': array.append('\t'); break; case 'b': array.append('\b'); break; case 'f': array.append('\f'); break; default: this.position = pos; throw new ConvertException("illegal escape(" + c + ") (position = " + this.position + ") in (" + new String(this.text) + ")"); } } else { array.append(c); } } } final static int[] digits = new int[255]; static { for (int i = 0; i < digits.length; i++) { digits[i] = -1; //-1 错误 } for (int i = '0'; i <= '9'; i++) { digits[i] = i - '0'; } for (int i = 'a'; i <= 'f'; i++) { digits[i] = i - 'a' + 10; } for (int i = 'A'; i <= 'F'; i++) { digits[i] = i - 'A' + 10; } digits['"'] = digits['\''] = -2; //-2 跳过 digits[' '] = digits['\t'] = digits['\r'] = digits['\n'] = -3; //-3可能跳过 digits[','] = digits['}'] = digits[']'] = digits[':'] = -4; //-4退出 } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy