Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG]fastjson 2.0.20, Enum序列化mixin与WriteEnumUsingToString同时配置时不起作用 #971

Closed
leonchen83 opened this issue Nov 28, 2022 · 3 comments
Labels
bug Something isn't working fixed
Milestone

Comments

@leonchen83
Copy link

leonchen83 commented Nov 28, 2022

问题描述

简要描述您碰到的问题。

环境信息

请填写以下信息:

  • OS信息: windows 10
  • JDK信息:jdk11
  • 版本信息:2.0.20

重现步骤

import static cn.nextop.gadget.json.Main.ABC.A;
import static com.alibaba.fastjson2.JSONWriter.Feature.WriteEnumUsingToString;
import static com.alibaba.fastjson2.JSONWriter.Feature.WriteNonStringKeyAsString;
import static com.alibaba.fastjson2.JSONWriter.Feature.WriteNulls;

import java.io.IOException;
import java.lang.reflect.Type;

import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.reader.ObjectReader;
import com.alibaba.fastjson2.reader.ObjectReaderProvider;
import com.alibaba.fastjson2.writer.ObjectWriter;
import com.alibaba.fastjson2.writer.ObjectWriterProvider;

/**
 * @author Baoyi Chen
 */
public class Main {
	public static void main(String[] args) throws IOException {
		Clazz t = new Clazz();
		t.setInt32(Misc.IntEnum.CLOSE);
		t.setInt64(Misc.LongEnum.HIGH);
		t.setAbc(A);
		
		Main main = new Main();
		String s = main.write(t);
		System.out.println(s); // 期望输出{"abc":"A","int32":10,"int64":100}, 实际输出{"abc":"A","int32":"CLOSE","int64":"HIGH"}
		
		String json = "{\"abc\":\"A\", \"int32\":10,\"int64\":100}";
		Clazz tt = main.read(json, Clazz.class);
		System.out.println(tt.int32);
		System.out.println(tt.int64);
		System.out.println(tt.abc);
	}
	
	public <T> T read(String json, Type type) {
		ObjectReaderProvider readers = new ObjectReaderProvider();
		readers.mixIn(Misc.PersistentEnum.class, PersistentEnumMixin.class);
		JSONReader.Context context = new JSONReader.Context(readers);
		try (final JSONReader reader = JSONReader.of(context, json)) {
			ObjectReader<T> v = reader.getObjectReader(type);
			return v.readObject(reader, 0);
		}
	}
	
	public String write(Object value) {
		ObjectWriterProvider writers = new ObjectWriterProvider();
		writers.mixIn(Misc.PersistentEnum.class, PersistentEnumMixin.class);
		JSONWriter.Context context = new JSONWriter.Context(writers);
		try (final JSONWriter writer = JSONWriter.of(context)) {
			if (value == null) writer.writeNull();
			else {
				context.config(WriteEnumUsingToString);
				context.config(WriteNonStringKeyAsString);
				context.config(WriteNulls);
				final Class<?> clazz = value.getClass();
				ObjectWriter<?> v = writer.getObjectWriter(clazz, clazz);
				v.write(writer, value, null, null, 0);
			}
			return writer.toString();
		}
	}
	
	public static enum ABC {
		A, B, C;
	}
	
	public static class Clazz {
		Misc.IntEnum int32;
		Misc.LongEnum int64;
		ABC abc;
		
		
		public Misc.IntEnum getInt32() {
			return int32;
		}
		
		public void setInt32(Misc.IntEnum int32) {
			this.int32 = int32;
		}
		
		public Misc.LongEnum getInt64() {
			return int64;
		}
		
		public void setInt64(Misc.LongEnum int64) {
			this.int64 = int64;
		}
		
		public ABC getAbc() {
			return abc;
		}
		
		public void setAbc(ABC abc) {
			this.abc = abc;
		}
	}
	
	public interface PersistentEnumMixin<T> {
		@JSONField(value = true)
		T getValue();
	}
}
import java.util.HashMap;
import java.util.Map;

/**
 * @author Baoyi Chen
 */
public class Misc {
	
	public static enum IntEnum implements PersistentEnum<Integer> {
		OPEN(6), CLOSE(10);
		
		int value;
		
		IntEnum(int value) {
			this.value = value;
		}
		
		@Override
		public Integer getValue() {
			return value;
		}
		
		@Override
		public Map<Integer, IntEnum> getAll() {
			Map<Integer, IntEnum> map = new HashMap<>();
			map.put(6, OPEN);
			map.put(10, CLOSE);
			return map;
		}
		
		public static IntEnum parse(int value) {
			if (value == OPEN.value) return OPEN;
			else if (value == CLOSE.value) return CLOSE;
			else throw new UnsupportedOperationException();
		}
	}
	
	public static enum LongEnum implements PersistentEnum<Long> {
		HIGH(100L), LOW(200L);
		
		long value;
		
		LongEnum(long value) {
			this.value = value;
		}
		
		@Override
		public Long getValue() {
			return value;
		}
		
		@Override
		public Map<Long, LongEnum> getAll() {
			Map<Long, LongEnum> map = new HashMap<>();
			map.put(100L, HIGH);
			map.put(200L, LOW);
			return map;
		}
		
		public static LongEnum parse(int value) {
			if (value == HIGH.value) return HIGH;
			else if (value == LOW.value) return LOW;
			else throw new UnsupportedOperationException();
		}
	}
	
	public interface PersistentEnum<T> {
		T getValue();
		
		Map<T, ? extends PersistentEnum<T>> getAll();
	}
	
}

期待的正确结果

{"abc":"A","int32":10,"int64":100}

相关日志实际输出

{"abc":"A","int32":"CLOSE","int64":"HIGH"}

附加信息

我们期望的是普通的Enum输出toString, 自己定义的PersistentEnum的时候,mixin有最高优先级
以上代码在2.0.18上是可以实际正确执行的,2.0.20才有此错误

@leonchen83 leonchen83 added the bug Something isn't working label Nov 28, 2022
@wenshao wenshao added this to the 2.0.21 milestone Nov 28, 2022
wenshao added a commit that referenced this issue Nov 30, 2022
@wenshao
Copy link
Member

wenshao commented Dec 1, 2022

https://oss.sonatype.org/content/repositories/snapshots/com/alibaba/fastjson2/fastjson2/2.0.21-SNAPSHOT/
我测试是好的,你能帮忙用2.0.21-SNAPSHOT快照版本验证下么?

@leonchen83
Copy link
Author

2.0.21-SNAPSHOT上述test可以通过

@wenshao wenshao added the fixed label Dec 2, 2022
@wenshao
Copy link
Member

wenshao commented Dec 10, 2022

https://github.com/alibaba/fastjson2/releases/tag/2.0.21
问题已修复,请用新版本

@wenshao wenshao closed this as completed Dec 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working fixed
Projects
None yet
Development

No branches or pull requests

2 participants